Was sind Attribute in .NET?

206

Was sind Attribute in .NET, wozu sind sie gut und wie erstelle ich meine eigenen Attribute?

Corey
quelle

Antworten:

146

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.

Streit
quelle
32
Für das, was es wert ist, ist dies eine Liste aller (eingebauten) .NET-Attribute: msdn.microsoft.com/en-us/library/aa311259(VS.71).aspx
wprl
1
Wie würden Sie Ihre "SomeProfilingMethod" als Attribut verwenden?
RayLoveless
@RayLoveless SomeProfilingMethod ist kein Attribut. Es handelt sich um den Instrumentierungscode, der nach Profilattributen sucht. Speziell in dem Beispiel habe ich nach einem "Opt-Out" -Attribut (NoTimingAttribute) im Gegensatz zu einem "Opt-In" -Attribut gesucht. Die Idee ist, dass es mal alles ist.
Quibblesome
@Quibblesome könnten Sie etwas hinzufügen wie "Attribute machen nichts für sich - es muss einen anderen Code geben, um sie zu verwenden (der Compiler kümmert sich um Paare, verschiedene Frameworks verwenden einige). Nur das Erstellen von Attributen hat keinen Einfluss auf das Verhalten des Codes." Sie müssen den anderen Teil schreiben, der Attribute überprüft (über Reflexion) und darauf reagieren. " (oder ich kann das tun, wenn es dir gut geht). Viele Menschen erwarten, dass Attribute auf magische Weise funktionieren, und keine der Antworten hier verdeutlicht dies. (oder einfach auf stackoverflow.com/questions/4879521/… verlinken, der es abdeckt)
Alexei Levenkov
Nur wenn Sie Bing nicht mehr verwenden. Nein, nein. j / k Ich benutze DuckDuckGo als meine primäre, die hauptsächlich Bing iirc verwendet. :)
Quibblesome
36

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 sealedKlassen 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:

  • Versammlung
  • Modul
  • Klasse
  • Struct
  • Aufzählung
  • Konstrukteur
  • Methode
  • Eigentum
  • Feld
  • Veranstaltung
  • Schnittstelle
  • Parameter
  • Delegieren
  • Rückgabewert
  • GenericParameter
  • Alles

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
Drew Noakes
quelle
13

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!

Patrik Svensson
quelle
5

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.

http://www.codeproject.com/KB/cs/dotnetattributes.aspx

Der Schlumpf
quelle
1
"Funktionalität" ist hier das falsche Wort; Sie sind Metadaten, keine Funktionalität
Marc Gravell
5

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

Stu
quelle
5

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 UserControleinem 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 ControlDescriptionAttributefü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.

Skizz
quelle
4

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.

Denis Phillips
quelle
3

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.

Urini
quelle
2

Um ein Attribut zu erstellen, öffnen Sie eine C # -Quelldatei, geben Sie ein attributeund drücken Sie [TAB]. Es wird zu einer Vorlage für ein neues Attribut erweitert.

Jay Bazuzi
quelle
6
Wie beantwortet es die Frage? Es sollte ein Kommentar sein, keine Antwort.
Gdoron unterstützt Monica
1

Attribute werden auch häufig für die aspektorientierte Programmierung verwendet. Ein Beispiel hierfür finden Sie im PostSharp- Projekt.

Josh G.
quelle