Tradus din această pagină oficială de documentație Microsoft.
Cerințe preliminare
Crearea aplicației
Cum adăugați atribute la cod
public class MyClass
{
Când marcați o clasă ca învechită, este o idee bună să oferiți ceva informație despre de ce este învechită, și/sau ce să se folosească în schimb. Faceți aceasta oferind un parametru șir la atributul Obsolete.
[Obsolete(„ThisClass este invechita. Folositi ThisClass2 in schimb.”)]
public class ThisClass
{
}
Parametrii către un constructor de atribut sunt limitați la tipuri simple/literali: bool, int, double, string, Type, enums, etc. și vectori de aceste tipuri. Nu puteți folosi o expresie sau variabilă. Sunteți liberi să folosiți parametrii poziționali sau numiți.
Cum vă creați propriul atribut
Crearea unui atribut este atât de simplu ca moștenind de la clasa bază Attribute.
public class MySpecialAttribute : Attribute
{
}
Cu ce e deasupra, pot acum folosi [MySpecial] (sau [MySpecialAttribute]) ca un atribut altundeva în codul de bază.
[MySpecial]
public class SomeOtherClass
{
}
Atributele din biblioteca de clase bază .NET precum ObsoleteAttribute delanșează unele comportamente în compilator. Totuși, orice atribut creați acționează doar ca metadate, și nu rezultă în execuția nici unui cod în clasa atribut. Depinde de dvs. să acționați pe baza acestor metadate altundeva în codul dvs. (mai multe despre aceasta mai în târziu în tutorial).
Există un „te-am prins” aici de care să aveți grijă. După cum s-a menționat mai sus, doar unele tipuri sunt permise să fie transmise ca argumente când se folosesc atribute. Totuși, când se creează un tip atribut, compilatorul C# nu vă va opri din a crea acești parametri. In exemplul de mai jos, am creat un atribut cu un constructor care compilează bine.
public class GotchaAttribute : Attribute
{
public GotchaAttribute(Foo myClass, string str) {
}
}
Totuși, dvs. nu veți putea să folosiți acest constructor cu sintaxa de atribut.
[Gotcha(new Foo(), „test”)] // nu compileaza
public class AttributeFail
{
}
Ce e mai sus va cauza o eroare de compilare precum
Cum restricționați utilizarea atributului
Atributele pot fi folosite pe un anumit număr de „ținte”. Exemplele de mai sus le arată pe clase, dar ele pot de asemenea fi folosite pe:
- ansamblu (Assembly)
- clasă
- constructor
- delegat
- enumerare
- eveniment
- câmp
- parametru generic
- interfață
- metodă
- modul
- parametru
- proprietate
- valoare de întoarcere
- structură
public class MyAttributeForClassAndStructOnly : Attribute
{
Dacă încercați să puneți atributul de mai sus pe ceva care nu este o clasă sau structură, veți primi o eroare de compilator ca Attribute ‘MyAttributeForClassAndStructOnly’ is not valid on this declaration type. It is only valid on ‘class, struct’ declarations.
public class Foo
{
// daca atributul de mai jos era necomentat, ar fi cauzat o eroare de compilator
// [MyAttributeForClassAndStructOnly]
public Foo()
{ }
}
Cum folosiți atribute atașate la un element de cod
Atributele se comportă ca metadate. Fără o fortă exterioară, ele nu vor face nimic de fapt.
Pentru a le găsi și a acționa pe atribute, Reflection este în general necesar. Nu voi acoperi Reflection în profunzime în acest tutorial, dar ideea de bază este că Reflection vă permite să scrieți cod în C# care examinează alt cod.
De exemplu, dvs. puteți folosi Reflection pentru a obține informații despre o clasă:
TypeInfo typeInfo = typeof(MyClass).GetTypeInfo();
Console.WriteLine(„Numele calificat de asamblare al MyClass este ” + typeInfo.AssemblyQualifiedName);
Aceasta va afișa ceva precum: Numele calificat de asamblare al MyClass este ConsoleApplication.MyClass, attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Odată ce aveți un obiect TypeInfo (sau un MemberInfo, FieldInfo, etc.), dvs. puteți folosi metoda GetCustomAttributes. Aceasta va returna o colecție de obiecte Attribute. Dvs. puteți de asemenea folosi GetCustomAttribute și specifica un tip Attribute.
Aici este un exemplu de utilizare a GetCustomAttributes pe o instanță MemberInfo pentru MyClass (pe care am văzut-o mai devreme că are un atribut [Obsolete] pe ea).
var attrs = typeInfo.GetCustomAttributes();
foreach(var attr in attrs)
Console.WriteLine(„Attribute pe MyClass: ” + attr.GetType().Name);
Aceasta va tipări în consolă: Attribute pe MyClass: ObsoleteAttribute. Incrcați să adăugați alte atribute la MyClass.
Este important să notați că aceste obiecte Attribute sunt inițializate leneș. Aceasta înseamnă, ele nu vor fi inițializate până când dvs. folosiți GetCustomAttribute sau GetCustomAttributes. Ele sunt de asemenea instanțiate de fiecare dată. Apelând GetCustomAttributes de două ori la rând va întoarce două instanțe diferite ale ObsoleteAttribute.
Atribute comune în biblioteca de bază de clase (BCL)
- [Obsolete]. Acesta a fost folosit în exemplele de mai sus, și trăiește în namespace-ul System. Este folositor în a furniza documentație declarativă despre cod de bază în schimbare. Un mesaj poate fi furnizat în forma unui șir, și un alt parametru boolean poate fi folosit pentru a escalada de la o avertizare de compilator la o eroare de compilator.
- [Conditional]. Acest atribut este în namespace-ul System.Diagnostics. Acest atribut poate fi folosit la metode (sau clase atribut). Dvs. trebuie să transmiteți un șir la constructor. Dacă acel șir se potrivește cu o directivă #define, atunci oricare apel la acea metodă (dar nu metoda însăși) va fi ștearsă de compilatorul C#. Uzual aceasta este folosită pentru scopuri de depanare (diagnosticare).
- [CallerMemberName]. Acest atribut poate fi folosit pe parametri, și trăiește în namespace-ul System.Runtime.CompilerServices. Acesta este un atribut care este folosit pentru a injecta numele metodei care apelează altă metodă. Uzual, acesta este folosit ca o cale de a elimina ‘șiruri magice’ când se implementează INotifyPropertyChanged în variate cadre de lucru de interfață grafică. Ca un exemplu:
{
public event PropertyChangedEventHandler PropertyChanged;
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public string Name
{
get { return _name;}
set
{
if (value != _name)
{
_name = value;
RaisePropertyChanged(); // notati ca nu e nevoie de „Name” aici in mod explicit
}
}
}
}
Sumar
Atributele aduc putere declarativă în C#. Dar ele sunt o formă de cod ca meta-date, și nu acționează prin ele însele.
Tradus din această pagină oficială de documentație Microsoft.