Antworten:
Metadaten. Daten zu Ihren Objekten / Methoden / Eigenschaften.
Zum Beispiel könnte ich ein Attribut mit dem Namen "DisplayOrder" deklarieren, damit ich leicht steuern kann, in welcher Reihenfolge Eigenschaften in der Benutzeroberfläche angezeigt werden sollen. Ich könnte es dann an eine Klasse anhängen und einige GUI-Komponenten schreiben, die die Attribute extrahieren und die UI-Elemente entsprechend anordnen.
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;
}
}
}
Dadurch wird sichergestellt, dass SomeInt immer vor SomeDate angezeigt wird, wenn mit meinen benutzerdefinierten GUI-Komponenten gearbeitet wird.
Sie werden sie jedoch am häufigsten außerhalb der direkten Codierungsumgebung verwenden. Zum Beispiel verwendet der Windows Designer sie ausgiebig, damit er weiß, wie er mit benutzerdefinierten Objekten umgeht. Verwenden Sie das BrowsableAttribute wie folgt:
[Browsable(false)]
public SomeCustomType DontShowThisInTheDesigner
{
get{/*do something*/}
}
Weist den Designer an, dies beispielsweise zur Entwurfszeit nicht in den verfügbaren Eigenschaften im Eigenschaftenfenster aufzulisten.
Sie können sie auch für die Codegenerierung, Vorkompilierungsvorgänge (z. B. Post-Sharp) oder Laufzeitvorgänge wie Reflection.Emit verwenden. Sie können beispielsweise ein Stück Code für die Profilerstellung schreiben, das jeden einzelnen Aufruf Ihres Codes transparent umschließt und zeitlich festlegt. Sie können das Timing über ein Attribut "deaktivieren", das Sie bestimmten Methoden zuweisen.
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);
}
}
Das Deklarieren ist einfach. Erstellen Sie einfach eine Klasse, die von Attribute erbt.
public class DisplayOrderAttribute : Attribute
{
private int order;
public DisplayOrderAttribute(int order)
{
this.order = order;
}
public int Order
{
get { return order; }
}
}
Und denken Sie daran, dass Sie bei Verwendung des Attributs das Suffix "Attribut" weglassen können, das der Compiler für Sie hinzufügt.
HINWEIS: Attribute machen nichts für sich - es muss einen anderen Code geben, der sie verwendet. Manchmal wurde dieser Code für Sie geschrieben, aber manchmal müssen Sie ihn selbst schreiben. Beispielsweise kümmert sich der C # -Compiler um einige und bestimmte Frameworks, für die Frameworks einige verwenden (z. B. sucht NUnit beim Laden einer Assembly nach [TestFixture] für eine Klasse und [Test] für eine Testmethode).
Beachten Sie daher beim Erstellen Ihres eigenen benutzerdefinierten Attributs, dass es das Verhalten Ihres Codes überhaupt nicht beeinflusst. Sie müssen den anderen Teil schreiben, der Attribute überprüft (über Reflexion) und darauf reagieren.
Viele Leute haben geantwortet, aber niemand hat dies bisher erwähnt ...
Attribute werden häufig mit Reflexion verwendet. Die Reflexion ist schon ziemlich langsam.
Es lohnt sich sehr , Ihre benutzerdefinierten Attribute als sealed
Klassen zu markieren , um ihre Laufzeitleistung zu verbessern.
Es ist auch eine gute Idee zu überlegen, wo es angebracht wäre, ein solches Attribut zu platzieren, und Ihr Attribut (!) Zuzuschreiben, um dies über anzuzeigen AttributeUsage
. Die Liste der verfügbaren Attributverwendungen könnte Sie überraschen:
Es ist auch cool, dass das AttributeUsage-Attribut Teil der Signatur des AttributeUsage-Attributs ist. Whoa für zirkuläre Abhängigkeiten!
[AttributeUsageAttribute(AttributeTargets.Class, Inherited = true)]
public sealed class AttributeUsageAttribute : Attribute
Attribute sind eine Art Metadaten zum Kennzeichnen von Klassen. Dies wird in WinForms häufig verwendet, um beispielsweise Steuerelemente in der Symbolleiste auszublenden. Es kann jedoch in Ihrer eigenen Anwendung implementiert werden, damit sich Instanzen verschiedener Klassen auf bestimmte Weise verhalten können.
Erstellen Sie zunächst ein Attribut:
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class SortOrderAttribute : Attribute
{
public int SortOrder { get; set; }
public SortOrderAttribute(int sortOrder)
{
this.SortOrder = sortOrder;
}
}
Alle Attributklassen müssen das Suffix "Attribut" haben, um gültig zu sein.
Erstellen Sie anschließend eine Klasse, die das Attribut verwendet.
[SortOrder(23)]
public class MyClass
{
public MyClass()
{
}
}
Jetzt können Sie eine bestimmte Klasse SortOrderAttribute
(falls vorhanden) überprüfen, indem Sie folgende Schritte ausführen:
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;
}
}
}
Wenn Sie mehr darüber lesen möchten, können Sie sich jederzeit MSDN ansehen, das eine ziemlich gute Beschreibung hat.
Ich hoffe das hat dir geholfen!
Ein Attribut ist eine Klasse, die einige Funktionen enthält, die Sie auf Objekte in Ihrem Code anwenden können. Erstellen Sie zum Erstellen einer Klasse eine Klasse, die von System.Attribute erbt.
Wofür sie gut sind ... es gibt fast unbegrenzte Verwendungsmöglichkeiten für sie.
Attribute sind wie Metadaten, die auf Klassen, Methoden oder Assemblys angewendet werden.
Sie eignen sich für eine beliebige Anzahl von Dingen (Debugger-Visualisierung, Markieren von Dingen als veraltet, Markieren von Dingen als serialisierbar, die Liste ist endlos).
Das Erstellen eigener benutzerdefinierter Elemente ist kinderleicht. Fang hier an:
http://msdn.microsoft.com/en-us/library/sw480ze8(VS.71).aspx
In dem Projekt, an dem ich gerade arbeite, gibt es eine Reihe von UI-Objekten verschiedener Varianten und einen Editor, um diese Objekte zusammenzusetzen und Seiten für die Verwendung in der Hauptanwendung zu erstellen, ähnlich wie beim Formulardesigner in DevStudio. Diese Objekte existieren in einer eigenen Assembly und jedes Objekt ist eine Klasse, die von UserControl
einem benutzerdefinierten Attribut abgeleitet ist und dieses hat. Dieses Attribut ist wie folgt definiert:
[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;
};
und ich wende es auf eine Klasse wie diese an:
[ControlDescription ("Pie Chart", "Displays a pie chart")]
public ref class PieControl sealed : UserControl
{
// stuff
};
Das haben die vorherigen Poster gesagt.
Um das Attribut zu verwenden, enthält der Editor Generic::List <Type>
die Steuerelementtypen. Es gibt ein Listenfeld, aus dem der Benutzer ziehen und auf die Seite legen kann, um eine Instanz des Steuerelements zu erstellen. Um das Listenfeld zu ControlDescriptionAttribute
füllen, erhalte ich das für das Steuerelement und fülle einen Eintrag in der Liste aus:
// 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;
}
}
Hinweis: Das obige ist C ++ / CLI, aber es ist nicht schwierig, in C # zu konvertieren (ja, ich weiß, C ++ / CLI ist ein Gräuel, aber es ist das, womit ich arbeiten muss :-()
Sie können den meisten Dingen Attribute zuweisen, und es gibt eine ganze Reihe vordefinierter Attribute. Der oben erwähnte Editor sucht auch nach benutzerdefinierten Attributen für Eigenschaften, die die Eigenschaft beschreiben und wie sie bearbeitet werden.
Sobald Sie die ganze Idee haben, werden Sie sich fragen, wie Sie jemals ohne sie gelebt haben.
Wie gesagt, Attribute sind relativ einfach zu erstellen. Der andere Teil der Arbeit besteht darin, Code zu erstellen, der ihn verwendet. In den meisten Fällen verwenden Sie Reflection zur Laufzeit, um das Verhalten basierend auf dem Vorhandensein eines Attributs oder seiner Eigenschaften zu ändern. Es gibt auch Szenarien, in denen Sie Attribute in kompiliertem Code untersuchen, um eine statische Analyse durchzuführen. Beispielsweise können Parameter als nicht null markiert werden, und das Analysetool kann dies als Hinweis verwenden.
Die Verwendung der Attribute und die Kenntnis der geeigneten Szenarien für ihre Verwendung machen den Großteil der Arbeit aus.
Attribute sind im Wesentlichen Datenbits, die Sie an Ihre Typen anhängen möchten (Klassen, Methoden, Ereignisse, Aufzählungen usw.).
Die Idee ist, dass zur Laufzeit ein anderer Typ / Framework / Tool Ihren Typ nach den Informationen im Attribut abfragt und darauf reagiert.
So kann Visual Studio beispielsweise die Attribute eines Steuerelements eines Drittanbieters abfragen, um herauszufinden, welche Eigenschaften des Steuerelements zur Entwurfszeit im Eigenschaftenbereich angezeigt werden sollen.
Attribute können auch in der aspektorientierten Programmierung verwendet werden, um Objekte zur Laufzeit basierend auf den Attributen, die sie dekorieren, einzufügen / zu bearbeiten und den Objekten Validierung, Protokollierung usw. hinzuzufügen, ohne die Geschäftslogik des Objekts zu beeinflussen.
Sie können benutzerdefinierte Attribute verwenden, um Tag-Werte in Unterklassen auf einfache Weise zu definieren, ohne für jede Unterklasse immer wieder denselben Code schreiben zu müssen. Ich bin auf ein schönes, kurzes Beispiel von John Waters gestoßen, wie man benutzerdefinierte Attribute in Ihrem eigenen Code definiert und verwendet.
Es gibt ein Tutorial unter http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx
Um ein Attribut zu erstellen, öffnen Sie eine C # -Quelldatei, geben Sie ein attribute
und drücken Sie [TAB]. Es wird zu einer Vorlage für ein neues Attribut erweitert.
Attribute werden auch häufig für die aspektorientierte Programmierung verwendet. Ein Beispiel hierfür finden Sie im PostSharp- Projekt.