C# Language
attributen
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; }
}
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."