Suche…


Benutzerdefiniertes Attribut erstellen

//1) All attributes should be inherited from System.Attribute
//2) You can customize your attribute usage (e.g. place restrictions) by using System.AttributeUsage Attribute
//3) You can use this attribute only via reflection in the way it is supposed to be used
//4) MethodMetadataAttribute is just a name. You can use it without "Attribute" postfix - e.g. [MethodMetadata("This text could be retrieved via reflection")].
//5) You can overload an attribute constructors
[System.AttributeUsage(System.AttributeTargets.Method | System.AttributeTargets.Class)]
public class MethodMetadataAttribute : System.Attribute
{
    //this is custom field given just for an example
    //you can create attribute without any fields
    //even an empty attribute can be used - as marker
    public string Text { get; set; }

    //this constructor could be used as [MethodMetadata]
    public MethodMetadataAttribute ()
    {
    }

    //This constructor could be used as [MethodMetadata("String")]
    public MethodMetadataAttribute (string text)
    {
        Text = text;
    }
}

Verwenden eines Attributs

[StackDemo(Text = "Hello, World!")]
public class MyClass
{
    [StackDemo("Hello, World!")]
    static void MyMethod()
    {
    }
}

Ein Attribut lesen

Die Methode GetCustomAttributes gibt ein Array von benutzerdefinierten Attributen zurück, die auf das Member angewendet werden. Nach dem Abrufen dieses Arrays können Sie nach einem oder mehreren bestimmten Attributen suchen.

var attribute = typeof(MyClass).GetCustomAttributes().OfType<MyCustomAttribute>().Single();

Oder durchlaufen sie

foreach(var attribute in typeof(MyClass).GetCustomAttributes()) {
    Console.WriteLine(attribute.GetType());
}

GetCustomAttribute Erweiterungsmethode GetCustomAttribute von System.Reflection.CustomAttributeExtensions ruft ein benutzerdefiniertes Attribut eines angegebenen Typs ab. Es kann auf jede MemberInfo angewendet werden.

var attribute = (MyCustomAttribute) typeof(MyClass).GetCustomAttribute(typeof(MyCustomAttribute));

GetCustomAttribute auch eine generische Signatur, um den Attributtyp anzugeben, nach dem gesucht werden soll.

var attribute = typeof(MyClass).GetCustomAttribute<MyCustomAttribute>();

Das boolesche Argument " inherit kann an beide Methoden übergeben werden. Wenn dieser Wert auf true gesetzt ist, sind die Vorfahren des Elements ebenfalls zu prüfen.

DebuggerDisplay-Attribut

Durch das Hinzufügen des DebuggerDisplay Attributs wird die Art und Weise geändert, in der der Debugger die Klasse anzeigt, wenn der DebuggerDisplay bewegt wird.

Ausdrücke, die in {} sind, werden vom Debugger ausgewertet. Dies kann eine einfache Eigenschaft wie im folgenden Beispiel oder eine komplexere Logik sein.

[DebuggerDisplay("{StringProperty} - {IntProperty}")]
public class AnObject
{
   public int ObjectId { get; set; }
   public string StringProperty { get; set; }
   public int IntProperty { get; set; }
}

DebuggerDisplay-Beispiel

Durch das Hinzufügen von ,nq vor der schließenden Klammer werden die Anführungszeichen entfernt, wenn eine Zeichenfolge ,nq .

[DebuggerDisplay("{StringProperty,nq} - {IntProperty}")]

Obwohl allgemeine Ausdrücke in {} zulässig sind, werden sie nicht empfohlen. Das DebuggerDisplay Attribut wird als String in die Assembly-Metadaten geschrieben. Ausdrücke in {} werden nicht auf Gültigkeit geprüft. Ein DebuggerDisplay Attribut, das eine komplexere Logik enthält als eine einfache Arithmetik, könnte in C # gut funktionieren, aber derselbe Ausdruck, der in VB.NET ausgewertet wird, ist wahrscheinlich nicht syntaktisch gültig und erzeugt beim Debuggen einen Fehler.

Eine Möglichkeit, DebuggerDisplay zu machen, besteht darin, den Ausdruck in eine Methode oder Eigenschaft zu schreiben und ihn stattdessen aufzurufen.

[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public class AnObject
{
   public int ObjectId { get; set; }
   public string StringProperty { get; set; }
   public int IntProperty { get; set; }

   private string DebuggerDisplay()
    {
        return $"{StringProperty} - {IntProperty}"";
    }
}

Man möchte, dass DebuggerDisplay alle oder nur einige der Eigenschaften ausgibt und beim Debuggen auch den Typ des Objekts überprüft.
Das folgende Beispiel umgibt auch die #if DEBUG mit #if DEBUG da DebuggerDisplay in Debugging-Umgebungen verwendet wird.

[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public class AnObject
{
   public int ObjectId { get; set; }
   public string StringProperty { get; set; }
   public int IntProperty { get; set; }

#if DEBUG
   private string DebuggerDisplay()
    {
        return
            $"ObjectId:{this.ObjectId}, StringProperty:{this.StringProperty}, Type:{this.GetType()}";
    }
    #endif
}

Attribute für Anruferinformationen

Anrufer-Info-Attribute können verwendet werden, um Informationen über den Aufrufer an die aufgerufene Methode weiterzuleiten. Die Deklaration sieht folgendermaßen aus:

using System.Runtime.CompilerServices;

public void LogException(Exception ex,
                         [CallerMemberName]string callerMemberName = "",
                         [CallerLineNumber]int callerLineNumber = 0,
                         [CallerFilePath]string callerFilePath = "")
{
    //perform logging
}

Und der Aufruf sieht so aus:

public void Save(DBContext context)
{
    try
    {
        context.SaveChanges();
    }
    catch (Exception ex)
    {
        LogException(ex);
    }
}

Beachten Sie, dass nur der erste Parameter explizit an die LogException Methode übergeben wird, während die übrigen Parameter zur Kompilierzeit mit den entsprechenden Werten versehen werden.

Der Parameter callerMemberName erhält den Wert "Save" - den Namen der aufrufenden Methode.

Der Parameter callerLineNumber erhält die Nummer der Zeile, in die der Aufruf der LogException Methode geschrieben wird.

Der Parameter 'callerFilePath' erhält den vollständigen Pfad der Datei, in der die Save Methode deklariert ist.

Ein Attribut von der Schnittstelle lesen

Es gibt keine einfache Möglichkeit, Attribute von einer Schnittstelle zu erhalten, da Klassen keine Attribute von einer Schnittstelle erben. Wenn Sie ein Interface implementieren oder Member in einer abgeleiteten Klasse überschreiben, müssen Sie die Attribute erneut deklarieren. In diesem Beispiel wäre die Ausgabe in allen drei Fällen also " True .

using System;
using System.Linq;
using System.Reflection;

namespace InterfaceAttributesDemo {
    
    [AttributeUsage(AttributeTargets.Interface, Inherited = true)]
    class MyCustomAttribute : Attribute {
        public string Text { get; set; }
    }
    
    [MyCustomAttribute(Text = "Hello from interface attribute")]
    interface IMyClass {
        void MyMethod();
    }
    
    class MyClass : IMyClass {
        public void MyMethod() { }
    }
    
    public class Program {
        public static void Main(string[] args) {
            GetInterfaceAttributeDemo();
        }
        
        private static void GetInterfaceAttributeDemo() {
            var attribute1 = (MyCustomAttribute) typeof(MyClass).GetCustomAttribute(typeof(MyCustomAttribute), true);
            Console.WriteLine(attribute1 == null); // True
            
            var attribute2 = typeof(MyClass).GetCustomAttributes(true).OfType<MyCustomAttribute>().SingleOrDefault();
            Console.WriteLine(attribute2 == null); // True
            
            var attribute3 = typeof(MyClass).GetCustomAttribute<MyCustomAttribute>(true);
            Console.WriteLine(attribute3 == null); // True
        }
    }
}

Eine Möglichkeit, Schnittstellenattribute abzurufen, besteht darin, über alle von einer Klasse implementierten Schnittstellen nach ihnen zu suchen.

var attribute = typeof(MyClass).GetInterfaces().SelectMany(x => x.GetCustomAttributes().OfType<MyCustomAttribute>()).SingleOrDefault();
Console.WriteLine(attribute == null); // False
Console.WriteLine(attribute.Text); // Hello from interface attribute

Veraltetes Attribut

System.Obsolete ist ein Attribut, mit dem ein Typ oder ein Member mit einer besseren Version markiert wird und daher nicht verwendet werden sollte.

[Obsolete("This class is obsolete. Use SomeOtherClass instead.")]
class SomeClass
{
    //
}

Wenn die Klasse oben verwendet wird, gibt der Compiler die Warnung "Diese Klasse ist veraltet. Verwenden Sie stattdessen SomeOtherClass."



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow