Delen via


Kenmerken

Kenmerken bieden een krachtige manier om metagegevens of declaratieve informatie te koppelen aan code (assembly's, typen, methoden, eigenschappen, enzovoort). Nadat u een kenmerk aan een programma-entiteit hebt gekoppeld, kunt u tijdens runtime een query uitvoeren op het kenmerk met behulp van een techniek met de naam weerspiegeling.

Kenmerken hebben de volgende eigenschappen:

  • Kenmerken voegen metagegevens toe aan uw programma. Metagegevens is informatie over de typen die in een programma zijn gedefinieerd. Alle .NET-assembly's bevatten een opgegeven set metagegevens waarmee de typen en typeleden worden beschreven die in de assembly zijn gedefinieerd. U kunt aangepaste kenmerken toevoegen om eventuele andere vereiste informatie op te geven.
  • Kenmerken kunnen worden toegepast op volledige assembly's, modules of kleinere programma-elementen, zoals klassen en eigenschappen.
  • Kenmerken kunnen argumenten op dezelfde manier accepteren als methoden en eigenschappen.
  • Met kenmerken kan een programma zijn eigen metagegevens of metagegevens in andere programma's onderzoeken met behulp van weerspiegeling.

Werken met reflectie

Reflectie API's die worden geleverd door Type assembly's, modules en typen beschrijven. U kunt reflectie gebruiken om dynamisch een exemplaar van een type te maken, het type aan een bestaand object te binden of het type op te halen uit een bestaand object en de methoden ervan aan te roepen of toegang te krijgen tot de velden en eigenschappen. Wanneer u attributen in uw code gebruikt, stelt reflectie u in staat om daar toegang toe te krijgen. Zie Kenmerkenvoor meer informatie.

Hier volgt een eenvoudig voorbeeld van weerspiegeling met de methode GetType(). Alle typen van de Object basisklasse nemen deze methode over, die wordt gebruikt om het type variabele te verkrijgen:

Notitie

Zorg ervoor dat u de using System;- en using System.Reflection;-instructies boven aan het codebestand C# (.cs) toevoegt.

// Using GetType to obtain type information:
int i = 42;
Type type = i.GetType();
Console.WriteLine(type);

De uitvoer toont het type:

System.Int32

In het volgende voorbeeld wordt reflectie gebruikt om de volledige naam van de geladen assembly te achterhalen.

// Using Reflection to get information of an Assembly:
Assembly info = typeof(int).Assembly;
Console.WriteLine(info);

De uitvoer is vergelijkbaar met het volgende voorbeeld:

System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e

Verschillen tussen trefwoorden voor IL

De C#-trefwoorden protected en internal hebben geen betekenis in Tussenliggende taal (IL) en worden niet gebruikt in de reflectie-API's. De bijbehorende termen in IL zijn Family en Assembly. Hier volgen enkele manieren waarop u deze voorwaarden kunt gebruiken:

  • Als u een internal methode wilt identificeren met behulp van weerspiegeling, gebruikt u de eigenschap IsAssembly.
  • Gebruik de protected internalom een IsFamilyOrAssembly methode te identificeren.

Werken met attributen

Kenmerken kunnen op vrijwel elke declaratie worden geplaatst, hoewel een specifiek kenmerk de typen declaraties kan beperken waarop deze geldig is. In C# geeft u een kenmerk op door de naam van het kenmerk tussen vierkante haken ([]) te plaatsen boven de declaratie van de entiteit waarop het van toepassing is.

In dit voorbeeld gebruikt u het kenmerk SerializableAttribute om een specifiek kenmerk toe te passen op een klasse:

[Serializable]
public class SampleClass
{
    // Objects of this type can be serialized.
}

U kunt een methode declareren met het kenmerk DllImportAttribute:

[System.Runtime.InteropServices.DllImport("user32.dll")]
extern static void SampleMethod();

U kunt meerdere kenmerken op een declaratie plaatsen:

void MethodA([In][Out] ref double x) { }
void MethodB([Out][In] ref double x) { }
void MethodC([In, Out] ref double x) { }

Sommige kenmerken kunnen meerdere keren worden opgegeven voor een bepaalde entiteit. In het volgende voorbeeld ziet u een multiuse van het kenmerk ConditionalAttribute:

[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
    // ...
}

Notitie

Standaard eindigen alle kenmerknamen met het achtervoegsel 'Kenmerk' om ze te onderscheiden van andere typen in de .NET-bibliotheken. U hoeft echter niet het kenmerkachtervoegsel op te geven wanneer u kenmerken in code gebruikt. Een [DllImport]-declaratie is bijvoorbeeld gelijk aan een [DllImportAttribute]-declaratie, maar DllImportAttribute is de werkelijke naam van de klasse in de .NET-klassebibliotheek.

Kenmerkparameters

Veel kenmerken hebben parameters, die kunnen worden positionele, naamlozeof met de naam. In de volgende tabel wordt beschreven hoe u werkt met benoemde en positionele kenmerken:

positionele parameters

Parameters van de kenmerkconstructor:

benoemde parameters

Eigenschappen of velden van het kenmerk:

  • Moet specificeren, mag niet weglaten
  • Altijd eerst specificeren
  • Opgeven in bepaalde volgorde
  • Altijd optioneel, weglaten wanneer onwaar
  • Geef op na positieparameters
  • Opgeven in een willekeurige volgorde

De volgende code toont bijvoorbeeld drie equivalente DllImport kenmerken:

[DllImport("user32.dll")]
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]

De eerste parameter, de DLL-naam, is positioneel en komt altijd als eerste. De andere instanties zijn benoemde parameters. In dit scenario worden beide benoemde parameters standaard ingesteld op false, zodat ze kunnen worden weggelaten. Raadpleeg de documentatie van het afzonderlijke kenmerk voor informatie over standaardparameterwaarden. Zie het gedeelte Kenmerken van de C#-taalspecificatievoor meer informatie over toegestane parametertypen.

Doelen voor attributen

Het doel van een kenmerk is de entiteit waarop het kenmerk van toepassing is. Een kenmerk kan bijvoorbeeld worden toegepast op een klasse, een methode of een assembly. Een kenmerk is standaard van toepassing op het element dat hierop volgt. Maar u kunt ook expliciet het element identificeren dat moet worden gekoppeld, zoals een methode, een parameter of de retourwaarde.

Gebruik de volgende syntaxis om expliciet een kenmerkdoel te identificeren:

[target : attribute-list]

In de volgende tabel ziet u de lijst met mogelijke target waarden.

Doelwaarde Van toepassing op
assembly Hele montage
module Huidige assemblagemodule
field Veld in een klasse of een structuur
event Gebeurtenis
method Methode ofwel get en set eigenschapstoegangsaccessors
param Methodeparameter(s) of set eigenschapstoegangsparameter(s)
property Eigendom
return Retourwaarde van een methode, eigenschapsindexeerfunctie of get eigenschapstoegangsfunctie
type Struct, klasse, interface, opsomming of gedelegeerde

U kunt de field doelwaarde opgeven om een kenmerk toe te passen op het backingveld dat is gemaakt voor een automatisch geïmplementeerde eigenschap.

In het volgende voorbeeld ziet u hoe u kenmerken toepast op assembly's en modules. Zie Common attributes (C#)voor meer informatie.

using System;
using System.Reflection;
[assembly: AssemblyTitleAttribute("Production assembly 4")]
[module: CLSCompliant(true)]

In het volgende voorbeeld ziet u hoe u kenmerken toepast op methoden, methodeparameters en waarden voor het retourneren van methoden in C#.

// default: applies to method
[ValidatedContract]
int Method1() { return 0; }

// applies to method
[method: ValidatedContract]
int Method2() { return 0; }

// applies to parameter
int Method3([ValidatedContract] string contract) { return 0; }

// applies to return value
[return: ValidatedContract]
int Method4() { return 0; }

Notitie

Ongeacht de doelen waarop het kenmerk ValidatedContract is gedefinieerd, moet het return doel worden opgegeven, zelfs als het kenmerk ValidatedContract is gedefinieerd om alleen op retourwaarden toe te passen. Met andere woorden, de compiler gebruikt de AttributeUsage informatie niet om dubbelzinnige kenmerkdoelen op te lossen. Zie AttributeUsagevoor meer informatie.

Manieren bekijken om kenmerken te gebruiken

Hier volgen enkele veelvoorkomende manieren om kenmerken in code te gebruiken:

  • Markeer controllermethoden die reageren op POST-berichten met behulp van het kenmerk HttpPost. Zie de HttpPostAttribute klas voor meer informatie.
  • Beschrijf hoe u parameters van de marshal-methode gebruikt bij het samenwerken met systeemeigen code. Zie de MarshalAsAttribute klas voor meer informatie.
  • COM-eigenschappen (Component Object Model) beschrijven voor klassen, methoden en interfaces.
  • Roep niet-beheerde code aan met behulp van de klasse DllImportAttribute.
  • Beschrijf uw assembly in termen van titel, versie, beschrijving of handelsmerk.
  • Beschrijven welke leden van een klasse moeten worden geserialiseerd voor persistentie.
  • Beschrijf hoe u een toewijzing kunt maken tussen klasseleden en XML-knooppunten voor XML-serialisatie.
  • Beschrijf de beveiligingsvereisten voor methoden.
  • Geef kenmerken op die worden gebruikt om beveiliging af te dwingen.
  • Controleer optimalisaties met de Just-In-Time-compiler (JIT) zodat de code gemakkelijk te debuggen blijft.
  • Informatie over de aanroeper voor een methode verkrijgen.

Scenario's voor reflectie bekijken

Weerspiegeling is handig in de volgende scenario's: