Réponses:
Métadonnées. Données sur vos objets / méthodes / propriétés.
Par exemple, je peux déclarer un attribut appelé: DisplayOrder afin que je puisse facilement contrôler dans quel ordre les propriétés doivent apparaître dans l'interface utilisateur. Je pourrais ensuite l'ajouter à une classe et écrire des composants GUI qui extraient les attributs et ordonnent les éléments d'interface utilisateur de manière appropriée.
public class DisplayWrapper
{
private UnderlyingClass underlyingObject;
public DisplayWrapper(UnderlyingClass u)
{
underlyingObject = u;
}
[DisplayOrder(1)]
public int SomeInt
{
get
{
return underlyingObject .SomeInt;
}
}
[DisplayOrder(2)]
public DateTime SomeDate
{
get
{
return underlyingObject .SomeDate;
}
}
}
Assurant ainsi que SomeInt est toujours affiché avant SomeDate lorsque vous travaillez avec mes composants GUI personnalisés.
Cependant, vous les verrez le plus souvent utilisés en dehors de l'environnement de codage direct. Par exemple, le concepteur Windows les utilise largement pour savoir comment gérer les objets personnalisés. Utiliser le BrowsableAttribute comme ceci:
[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
get{/*do something*/}
}
Indique au concepteur de ne pas répertorier cela dans les propriétés disponibles dans la fenêtre Propriétés au moment du design par exemple.
Vous pouvez également les utiliser pour la génération de code, les opérations de précompilation (telles que Post-Sharp) ou les opérations d'exécution telles que Reflection.Emit. Par exemple, vous pouvez écrire un peu de code pour le profilage qui enveloppe de manière transparente chaque appel de votre code et le chronomètre. Vous pouvez "désactiver" le timing via un attribut que vous placez sur des méthodes particulières.
public void SomeProfilingMethod(MethodInfo targetMethod, object target, params object[] args)
{
bool time = true;
foreach (Attribute a in target.GetCustomAttributes())
{
if (a.GetType() is NoTimingAttribute)
{
time = false;
break;
}
}
if (time)
{
StopWatch stopWatch = new StopWatch();
stopWatch.Start();
targetMethod.Invoke(target, args);
stopWatch.Stop();
HandleTimingOutput(targetMethod, stopWatch.Duration);
}
else
{
targetMethod.Invoke(target, args);
}
}
Les déclarer est facile, créez simplement une classe qui hérite d'Attribute.
public class DisplayOrderAttribute : Attribute
{
private int order;
public DisplayOrderAttribute(int order)
{
this.order = order;
}
public int Order
{
get { return order; }
}
}
Et rappelez-vous que lorsque vous utilisez l'attribut, vous pouvez omettre le suffixe "attribut", le compilateur l'ajoutera pour vous.
REMARQUE: les attributs ne font rien par eux-mêmes - il doit y avoir un autre code qui les utilise. Parfois, ce code a été écrit pour vous, mais parfois vous devez l'écrire vous-même. Par exemple, le compilateur C # se soucie de certains frameworks et certains frameworks en utilisent certains (par exemple NUnit recherche [TestFixture] sur une classe et [Test] sur une méthode de test lors du chargement d'un assembly).
Ainsi, lorsque vous créez votre propre attribut personnalisé, sachez que cela n'affectera pas du tout le comportement de votre code. Vous devrez écrire l'autre partie qui vérifie les attributs (via la réflexion) et agir sur eux.
Beaucoup de gens ont répondu mais personne ne l'a mentionné jusqu'à présent ...
Les attributs sont largement utilisés avec la réflexion. La réflexion est déjà assez lente.
Il est très utile de marquer vos attributs personnalisés comme étant des sealed
classes pour améliorer leurs performances d'exécution.
C'est aussi une bonne idée de considérer où il serait approprié d'utiliser place un tel attribut, et d'attribuer votre attribut (!) Pour l'indiquer via AttributeUsage
. La liste des utilisations d'attributs disponibles peut vous surprendre:
Il est également cool que l'attribut AttributeUsage fasse partie de la signature de l'attribut AttributeUsage. Whoa pour les dépendances circulaires!
[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute
Les attributs sont une sorte de métadonnées pour les classes de marquage. Ceci est souvent utilisé dans WinForms par exemple pour masquer les contrôles de la barre d'outils, mais peut être implémenté dans votre propre application pour permettre aux instances de différentes classes de se comporter de manière spécifique.
Commencez par créer un attribut:
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class SortOrderAttribute : Attribute
{
public int SortOrder { get; set; }
public SortOrderAttribute(int sortOrder)
{
this.SortOrder = sortOrder;
}
}
Toutes les classes d'attributs doivent avoir le suffixe "Attribut" pour être valides.
Après cela, créez une classe qui utilise l'attribut.
[SortOrder(23)]
public class MyClass
{
public MyClass()
{
}
}
Vous pouvez maintenant vérifier une classe spécifique ' SortOrderAttribute
(si elle en a une) en procédant comme suit:
public class MyInvestigatorClass
{
public void InvestigateTheAttribute()
{
// Get the type object for the class that is using
// the attribute.
Type type = typeof(MyClass);
// Get all custom attributes for the type.
object[] attributes = type.GetCustomAttributes(
typeof(SortOrderAttribute), true);
// Now let's make sure that we got at least one attribute.
if (attributes != null && attributes.Length > 0)
{
// Get the first attribute in the list of custom attributes
// that is of the type "SortOrderAttribute". This should only
// be one since we said "AllowMultiple=false".
SortOrderAttribute attribute =
attributes[0] as SortOrderAttribute;
// Now we can get the sort order for the class "MyClass".
int sortOrder = attribute.SortOrder;
}
}
}
Si vous voulez en savoir plus à ce sujet, vous pouvez toujours consulter MSDN qui a une assez bonne description.
J'espère que cela vous a aidé!
Un attribut est une classe qui contient des fonctionnalités que vous pouvez appliquer aux objets de votre code. Pour en créer une, créez une classe qui hérite de System.Attribute.
Quant à ce à quoi ils sont bons ... il y a des utilisations presque illimitées pour eux.
Les attributs sont comme des métadonnées appliquées à des classes, des méthodes ou des assemblys.
Ils sont bons pour un certain nombre de choses (visualisation du débogueur, marquage des choses comme obsolètes, marquage des choses comme sérialisables, la liste est infinie).
Il est facile de créer vos propres modèles personnalisés. Commencer ici:
http://msdn.microsoft.com/en-us/library/sw480ze8(VS.71).aspx
Dans le projet sur lequel je travaille actuellement, il y a un ensemble d'objets d'interface utilisateur de différentes saveurs et un éditeur pour assembler ces objets pour créer des pages à utiliser dans l'application principale, un peu comme le concepteur de formulaires dans DevStudio. Ces objets existent dans leur propre assemblage et chaque objet est une classe dérivée de UserControl
et possède un attribut personnalisé. Cet attribut est défini comme ceci:
[AttributeUsage (AttributeTargets::Class)]
public ref class ControlDescriptionAttribute : Attribute
{
public:
ControlDescriptionAttribute (String ^name, String ^description) :
_name (name),
_description (description)
{
}
property String ^Name
{
String ^get () { return _name; }
}
property String ^Description
{
String ^get () { return _description; }
}
private:
String
^ _name,
^ _description;
};
et je l'applique à une classe comme celle-ci:
[ControlDescription ("Pie Chart", "Displays a pie chart")]
public ref class PieControl sealed : UserControl
{
// stuff
};
c'est ce que les affiches précédentes ont dit.
Pour utiliser l'attribut, l'éditeur a un Generic::List <Type>
contenant les types de contrôle. Il existe une zone de liste à partir de laquelle l'utilisateur peut faire glisser et déposer sur la page pour créer une instance du contrôle. Pour remplir la zone de liste, j'obtiens le ControlDescriptionAttribute
contrôle et remplis une entrée dans la liste:
// done for each control type
array <Object ^>
// get all the custom attributes
^attributes = controltype->GetCustomAttributes (true);
Type
// this is the one we're interested in
^attributetype = ECMMainPageDisplay::ControlDescriptionAttribute::typeid;
// iterate over the custom attributes
for each (Object ^attribute in attributes)
{
if (attributetype->IsInstanceOfType (attribute))
{
ECMMainPageDisplay::ControlDescriptionAttribute
^description = safe_cast <ECMMainPageDisplay::ControlDescriptionAttribute ^> (attribute);
// get the name and description and create an entry in the list
ListViewItem
^item = gcnew ListViewItem (description->Name);
item->Tag = controltype->Name;
item->SubItems->Add (description->Description);
mcontrols->Items->Add (item);
break;
}
}
Remarque: ce qui précède est C ++ / CLI mais ce n'est pas difficile à convertir en C # (ouais, je sais, C ++ / CLI est une abomination mais c'est avec cela que je dois travailler :-()
Vous pouvez mettre des attributs sur la plupart des choses et il existe toute une gamme d'attributs prédéfinis. L'éditeur mentionné ci-dessus recherche également des attributs personnalisés sur les propriétés qui décrivent la propriété et comment la modifier.
Une fois que vous aurez compris l'idée, vous vous demanderez comment vous avez pu vivre sans eux.
Comme dit précédemment, les attributs sont relativement faciles à créer. L'autre partie du travail consiste à créer du code qui l'utilise. Dans la plupart des cas, vous utiliserez la réflexion lors de l'exécution pour modifier le comportement en fonction de la présence d'un attribut ou de ses propriétés. Il existe également des scénarios dans lesquels vous inspecterez les attributs du code compilé pour effectuer une sorte d'analyse statique. Par exemple, les paramètres peuvent être marqués comme non nuls et l'outil d'analyse peut l'utiliser comme indice.
L'utilisation des attributs et la connaissance des scénarios appropriés pour leur utilisation constituent l'essentiel du travail.
Les attributs sont, essentiellement, des bits de données que vous souhaitez associer à vos types (classes, méthodes, événements, énumérations, etc.)
L'idée est qu'au moment de l'exécution, un autre type / framework / outil interrogera votre type pour les informations dans l'attribut et agira en conséquence.
Ainsi, par exemple, Visual Studio peut interroger les attributs d'un contrôle tiers pour déterminer quelles propriétés du contrôle doivent apparaître dans le volet Propriétés au moment du design.
Les attributs peuvent également être utilisés dans la programmation orientée aspect pour injecter / manipuler des objets au moment de l'exécution en fonction des attributs qui les décorent et ajouter la validation, la journalisation, etc. aux objets sans affecter la logique métier de l'objet.
Vous pouvez utiliser des attributs personnalisés comme un moyen simple de définir des valeurs de balise dans des sous-classes sans avoir à écrire le même code encore et encore pour chaque sous-classe. Je suis tombé sur un bel exemple concis de John Waters sur la façon de définir et d'utiliser des attributs personnalisés dans votre propre code.
Il existe un didacticiel sur http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx
Pour commencer à créer un attribut, ouvrez un fichier source C #, tapez attribute
et appuyez sur [TAB]. Il se développera en un modèle pour un nouvel attribut.