Risposte:
Metadati. Dati sui tuoi oggetti / metodi / proprietà.
Ad esempio, potrei dichiarare un attributo chiamato: DisplayOrder in modo da poter facilmente controllare in quale ordine le proprietà dovrebbero apparire nell'interfaccia utente. Potrei quindi aggiungerlo a una classe e scrivere alcuni componenti della GUI che estraggono gli attributi e ordinano gli elementi dell'interfaccia utente in modo appropriato.
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;
}
}
}
In tal modo assicurando che SomeInt sia sempre visualizzato prima di SomeDate quando si lavora con i miei componenti della GUI personalizzati.
Tuttavia, li vedrai più comunemente usati al di fuori dell'ambiente di codifica diretta. Ad esempio, Windows Designer li utilizza ampiamente in modo da sapere come gestire oggetti personalizzati. Utilizzando il BrowsableAttribute in questo modo:
[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
get{/*do something*/}
}
Indica al designer di non elencarlo nelle proprietà disponibili nella finestra Proprietà in fase di progettazione, ad esempio.
Si potrebbe anche usarli per il codice-generazione, le operazioni di pre-compilazione (come post-Sharp) operazioni o di run-time come Reflection.Emit. Ad esempio, potresti scrivere un po 'di codice per la profilatura che ha avvolto in modo trasparente ogni singola chiamata effettuata dal tuo codice e che l'ha ripetuto. È possibile "annullare" il tempismo tramite un attributo che si posiziona su metodi particolari.
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);
}
}
Dichiararli è facile, basta creare una classe che eredita da Attributo.
public class DisplayOrderAttribute : Attribute
{
private int order;
public DisplayOrderAttribute(int order)
{
this.order = order;
}
public int Order
{
get { return order; }
}
}
E ricorda che quando usi l'attributo puoi omettere il suffisso "attributo" che il compilatore aggiungerà per te.
NOTA: gli attributi non fanno nulla da soli - deve esserci un altro codice che li utilizza. A volte quel codice è stato scritto per te ma a volte devi scriverlo da solo. Ad esempio, il compilatore C # si preoccupa di alcuni e alcuni frameworks usano alcuni framework (ad esempio NUnit cerca [TestFixture] su una classe e [Test] su un metodo di test durante il caricamento di un assembly).
Pertanto, quando crei il tuo attributo personalizzato, tieni presente che non avrà alcun impatto sul comportamento del tuo codice. Dovrai scrivere l'altra parte che controlla gli attributi (tramite la riflessione) e agire su di essi.
Molte persone hanno risposto, ma nessuno ha menzionato questo finora ...
Gli attributi sono usati pesantemente con la riflessione. La riflessione è già piuttosto lenta.
Vale la pena contrassegnare gli attributi personalizzati come sealed
classi per migliorare le prestazioni di runtime.
È anche una buona idea considerare dove sarebbe opportuno utilizzare un tale attributo e attribuire il tuo attributo (!) Per indicarlo tramite AttributeUsage
. L'elenco degli utilizzi degli attributi disponibili potrebbe sorprenderti:
È anche bello che l'attributo AttributeUsage faccia parte della firma dell'attributo AttributeUsage. Whoa per dipendenze circolari!
[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute
Gli attributi sono una sorta di metadati per le classi di tagging. Questo è spesso usato in WinForms per esempio per nascondere i controlli dalla barra degli strumenti, ma può essere implementato nella propria applicazione per consentire alle istanze di classi diverse di comportarsi in modi specifici.
Inizia creando un attributo:
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class SortOrderAttribute : Attribute
{
public int SortOrder { get; set; }
public SortOrderAttribute(int sortOrder)
{
this.SortOrder = sortOrder;
}
}
Tutte le classi di attributi devono avere il suffisso "Attributo" per essere valide.
Al termine, creare una classe che utilizza l'attributo.
[SortOrder(23)]
public class MyClass
{
public MyClass()
{
}
}
Ora puoi controllare una classe specifica ' SortOrderAttribute
(se ne ha una) procedendo come segue:
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;
}
}
}
Se vuoi leggere di più su questo puoi sempre dare un'occhiata a MSDN che ha una descrizione abbastanza buona.
Spero che questo ti abbia aiutato!
Un attributo è una classe che contiene alcune funzionalità che è possibile applicare agli oggetti nel codice. Per crearne uno, crea una classe che eredita da System.Attribute.
Per quanto riguarda ciò a cui servono ... ci sono usi quasi illimitati per loro.
Gli attributi sono come metadati applicati a classi, metodi o assiemi.
Sono utili per qualsiasi numero di cose (visualizzazione del debugger, contrassegnare le cose come obsolete, contrassegnare le cose come serializzabili, l'elenco è infinito).
Creare i tuoi personalizzati è facile come una torta. Comincia qui:
http://msdn.microsoft.com/en-us/library/sw480ze8(VS.71).aspx
Nel progetto a cui sto attualmente lavorando, c'è una serie di oggetti dell'interfaccia utente di vari gusti e un editor per assemblare questi oggetti per creare pagine da utilizzare nell'applicazione principale, un po 'come il progettista di moduli in DevStudio. Questi oggetti esistono nel loro proprio assieme e ogni oggetto è una classe derivata UserControl
e ha un attributo personalizzato. Questo attributo è definito come questo:
[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;
};
e lo applico a una classe come questa:
[ControlDescription ("Pie Chart", "Displays a pie chart")]
public ref class PieControl sealed : UserControl
{
// stuff
};
che è quello che hanno detto i precedenti poster.
Per utilizzare l'attributo, l'editor ha un Generic::List <Type>
contenente i tipi di controllo. C'è una casella di riepilogo da cui l'utente può trascinare e rilasciare sulla pagina per creare un'istanza del controllo. Per popolare la casella di riepilogo, ottengo ControlDescriptionAttribute
il controllo e compilo una voce nell'elenco:
// 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;
}
}
Nota: quanto sopra è C ++ / CLI ma non è difficile convertirlo in C # (sì, lo so, C ++ / CLI è un abominio ma è quello con cui devo lavorare :-()
Puoi mettere gli attributi sulla maggior parte delle cose e ci sono tutta una gamma di attributi predefiniti. L'editor sopra menzionato cerca anche attributi personalizzati sulle proprietà che descrivono la proprietà e come modificarla.
Una volta che avrai avuto l'idea, ti chiederai come hai mai vissuto senza di loro.
Come detto, gli attributi sono relativamente facili da creare. L'altra parte del lavoro è la creazione di codice che lo utilizza. Nella maggior parte dei casi utilizzerai la riflessione in fase di esecuzione per modificare il comportamento in base alla presenza di un attributo o alle sue proprietà. Esistono anche scenari in cui ispezionerai gli attributi del codice compilato per eseguire una sorta di analisi statica. Ad esempio, i parametri potrebbero essere contrassegnati come non nulli e lo strumento di analisi può utilizzare questo come suggerimento.
L'uso degli attributi e la conoscenza degli scenari appropriati per il loro uso è la maggior parte del lavoro.
Gli attributi sono essenzialmente frammenti di dati che vuoi allegare ai tuoi tipi (classi, metodi, eventi, enum, ecc.)
L'idea è che in fase di esecuzione qualche altro tipo / framework / tool interrogherà il tuo tipo per le informazioni nell'attributo e agirà su di esso.
Quindi, ad esempio, Visual Studio può interrogare gli attributi su un controllo di terze parti per capire quali proprietà del controllo dovrebbero apparire nel riquadro Proprietà in fase di progettazione.
Gli attributi possono anche essere utilizzati nella programmazione orientata all'aspetto per iniettare / manipolare oggetti in fase di esecuzione in base agli attributi che li decorano e aggiungere la convalida, la registrazione, ecc. Agli oggetti senza influire sulla logica aziendale dell'oggetto.
È possibile utilizzare gli attributi personalizzati come un modo semplice per definire i valori dei tag nelle sottoclassi senza dover scrivere più volte lo stesso codice per ogni sottoclasse. Mi sono imbattuto in un bell'esempio conciso di John Waters su come definire e usare attributi personalizzati nel tuo codice.
C'è un tutorial su http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx
Per iniziare a creare un attributo, apri un file sorgente C #, digita attribute
e premi [TAB]. Si espanderà in un modello per un nuovo attributo.