Zoeken…


Een aangepast kenmerk maken

//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;
    }
}

Een attribuut gebruiken

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

Een attribuut lezen

Methode GetCustomAttributes retourneert een reeks aangepaste attributen die op het lid zijn toegepast. Na het ophalen van deze array kunt u zoeken naar een of meer specifieke kenmerken.

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

Of doorloop ze

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

GetCustomAttribute uitbreidingsmethode van System.Reflection.CustomAttributeExtensions haalt een aangepast kenmerk van een bepaald type op, het kan op elke MemberInfo worden toegepast.

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

GetCustomAttribute ook een generieke handtekening om het type kenmerk op te geven GetCustomAttribute moet worden gezocht.

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

Boolean argument inherit kan worden doorgegeven aan beide methoden. Als deze waarde wordt ingesteld op true de voorouders van het element ook geïnspecteerd.

DebuggerDisplay-kenmerk

Door het DebuggerDisplay voegen, wordt de manier gewijzigd waarop de debugger de klasse weergeeft wanneer deze wordt bewogen.

Uitdrukkingen die zijn ingepakt in {} worden geëvalueerd door de debugger. Dit kan een eenvoudige eigenschap zijn zoals in het volgende voorbeeld of meer complexe logica.

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

Voorbeeld van foutopsporing

Als u ,nq vóór de afsluitende haak, worden de aanhalingstekens verwijderd bij het uitvoeren van een string.

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

Hoewel algemene uitdrukkingen zijn toegestaan in de {} , worden deze niet aanbevolen. Het kenmerk DebuggerDisplay wordt als een tekenreeks in de assemblagemetagegevens geschreven. Uitdrukkingen in {} worden niet op geldigheid gecontroleerd. Dus een DebuggerDisplay attribuut dat complexere logica bevat dan dat een eenvoudige rekenkunde misschien goed werkt in C #, maar dezelfde expressie die wordt geëvalueerd in VB.NET zal waarschijnlijk niet syntactisch geldig zijn en een fout veroorzaken tijdens het debuggen.

Een manier om DebuggerDisplay meer agnostisch te maken, is door de uitdrukking in een methode of eigenschap te schrijven en in plaats daarvan aan te roepen.

[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}"";
    }
}

Men zou willen dat DebuggerDisplay alle of slechts enkele eigenschappen uitvoert en bij het debuggen en inspecteren ook het type object.
Het onderstaande voorbeeld omgeeft de helpermethode met #if DEBUG omdat DebuggerDisplay wordt gebruikt in foutopsporingsomgevingen.

[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
}

Beller info attributen

Beller info attributen kunnen worden gebruikt om informatie over de invoker door te geven aan de aangeroepen methode. De verklaring ziet er als volgt uit:

using System.Runtime.CompilerServices;

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

En de aanroep ziet er zo uit:

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

Merk op dat alleen de eerste parameter expliciet wordt doorgegeven aan de LogException methode, terwijl de rest tijdens het compileren wordt verstrekt met de relevante waarden.

De parameter callerMemberName ontvangt de waarde "Save" - de naam van de aanroepingsmethode.

De parameter callerLineNumber ontvangt het nummer van elke regel waarop de LogException de LogException methode is geschreven.

En de parameter 'callerFilePath' ontvangt het volledige pad van de methode Bestand Save is aangegeven in.

Een kenmerk uit de interface lezen

Er is geen eenvoudige manier om attributen van een interface te verkrijgen, omdat klassen geen attributen van een interface erven. Wanneer u een interface implementeert of leden in een afgeleide klasse overschrijft, moet u de kenmerken opnieuw opgeven. Dus in het voorbeeld hieronder uitgang zou zijn True in alle drie gevallen.

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
        }
    }
}

Een manier om interface-kenmerken op te halen, is om ze te zoeken via alle interfaces die door een klasse zijn geïmplementeerd.

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

Verouderd kenmerk

System.Obsolete is een attribuut dat wordt gebruikt om een type of een lid te markeren dat een betere versie heeft en daarom niet mag worden gebruikt.

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

Als de bovenstaande klasse wordt gebruikt, geeft de compiler de waarschuwing "Deze klasse is verouderd. Gebruik in plaats daarvan SomeOtherClass."



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow