Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Atrybuty zapewniają zaawansowany sposób kojarzenia metadanych lub informacji deklaratywnych z kodem (zestawy, typy, metody, właściwości itd.). Po skojarzeniu atrybutu z jednostką programu można wykonać zapytanie dotyczące atrybutu w czasie wykonywania przy użyciu techniki o nazwie odbicie.
Atrybuty mają następujące właściwości:
- Atrybuty dodają metadane do programu. Metadata to informacje o typach zdefiniowanych w programie. Wszystkie zestawy platformy .NET zawierają określony zestaw metadanych, który opisuje typy i składowe typu zdefiniowane w zestawie. Możesz dodać atrybuty niestandardowe, aby określić inne wymagane informacje.
- Atrybuty można stosować do całych zestawów, modułów lub mniejszych elementów programu, takich jak klasy i właściwości.
- Atrybuty mogą akceptować argumenty w taki sam sposób jak metody i właściwości.
- Atrybuty umożliwiają programowi badanie własnych metadanych lub metadanych w innych programach przy użyciu odbicia.
Praca z refleksją
API refleksji udostępniane przez Type opisują zestawy, moduły i typy. Można użyć odbicia, aby dynamicznie utworzyć wystąpienie typu, powiązać typ z istniejącym obiektem lub pobrać typ z istniejącego obiektu i wywołać jego metody lub uzyskać dostęp do jego pól i właściwości. Gdy używasz atrybutów w kodzie, odbicie umożliwia dostęp do nich. Aby uzyskać więcej informacji, zobacz Atrybuty.
Oto prosty przykład odbicia za pomocą metody GetType(). Wszystkie typy z klasy bazowej Object
dziedziczą tę metodę, która jest używana do uzyskiwania typu zmiennej:
Uwaga
Upewnij się, że dodano instrukcje using System;
i using System.Reflection;
w górnej części pliku kodu C# (.cs).
// Using GetType to obtain type information:
int i = 42;
Type type = i.GetType();
Console.WriteLine(type);
Dane wyjściowe zawierają typ:
System.Int32
W poniższym przykładzie użyto reflection w celu uzyskania pełnej nazwy załadowanego zestawu.
// Using Reflection to get information of an Assembly:
Assembly info = typeof(int).Assembly;
Console.WriteLine(info);
Dane wyjściowe są podobne do poniższego przykładu:
System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
Różnice słów kluczowych dla IL
Słowa kluczowe języka C# protected
i internal
nie mają znaczenia w języku pośrednim (IL) i nie są używane w interfejsach API odbicia. Odpowiednie terminy w IL to Rodzina i Zgromadzenie. Poniżej przedstawiono kilka sposobów używania następujących terminów:
- Aby zidentyfikować metodę
internal
przy użyciu odbicia, użyj właściwości IsAssembly. - Aby zidentyfikować metodę
protected internal
, użyj IsFamilyOrAssembly.
Praca z atrybutami
Atrybuty można umieścić na prawie każdej deklaracji, choć określony atrybut może ograniczyć typy deklaracji, na których jest prawidłowy. W języku C#należy określić atrybut, umieszczając nazwę atrybutu ujętego w nawiasy kwadratowe ([]
) powyżej deklaracji jednostki, do której ma zastosowanie.
W tym przykładzie użyjesz atrybutu SerializableAttribute, aby zastosować konkretną charakterystykę do klasy:
[Serializable]
public class SampleClass
{
// Objects of this type can be serialized.
}
Metodę można zadeklarować za pomocą atrybutu DllImportAttribute:
[System.Runtime.InteropServices.DllImport("user32.dll")]
extern static void SampleMethod();
Można umieścić wiele atrybutów w deklaracji:
void MethodA([In][Out] ref double x) { }
void MethodB([Out][In] ref double x) { }
void MethodC([In, Out] ref double x) { }
Niektóre atrybuty można określić więcej niż raz dla danej jednostki. W poniższym przykładzie pokazano wielokrotne użycie atrybutu ConditionalAttribute.
[Conditional("DEBUG"), Conditional("TEST1")]
void TraceMethod()
{
// ...
}
Uwaga
Zgodnie z konwencją wszystkie nazwy atrybutów kończą się sufiksem "Atrybut", aby odróżnić je od innych typów w bibliotekach platformy .NET. Nie trzeba jednak określać sufiksu atrybutu podczas używania atrybutów w kodzie. Na przykład deklaracja [DllImport]
jest równoważna deklaracji [DllImportAttribute]
, ale DllImportAttribute
jest rzeczywistą nazwą klasy w bibliotece klas platformy .NET.
Parametry atrybutów
Wiele atrybutów ma parametry, które mogą być pozycyjne, bezimiennelub nazwane. W poniższej tabeli opisano sposób pracy z nazwanymi i pozycyjnymi atrybutami:
parametry pozycyjne
Parametry konstruktora atrybutu:
nazwane parametry
Właściwości lub pola atrybutu:
- Musi określić, nie można pominąć
- Najpierw zawsze określaj
- Określ w pewnej kolejności
- Zawsze opcjonalny, pomiń, jeśli fałszywy
- Określ po parametrach pozycyjnych
- Określ w dowolnej kolejności
Na przykład poniższy kod przedstawia trzy równoważne atrybuty DllImport
:
[DllImport("user32.dll")]
[DllImport("user32.dll", SetLastError=false, ExactSpelling=false)]
[DllImport("user32.dll", ExactSpelling=false, SetLastError=false)]
Pierwszy parametr, nazwa biblioteki DLL, jest pozycyjny i zawsze pojawia się jako pierwszy. Inne wystąpienia są nazwane parametrami. W tym scenariuszu oba nazwane parametry domyślnie mają wartość false, aby można je było pominąć. Zapoznaj się z dokumentacją poszczególnych atrybutów, aby uzyskać informacje na temat domyślnych wartości parametrów. Aby uzyskać więcej informacji na temat dozwolonych typów parametrów, zobacz sekcję Attributes w specyfikacji języka C#.
Cele atrybutów
docelowym atrybutu jest jednostka, do której ten atrybut się odnosi. Na przykład atrybut może być stosowany do klasy, metody lub zestawu. Domyślnie atrybut ma zastosowanie do elementu, który następuje po nim. Można jednak jawnie zidentyfikować element do skojarzenia, na przykład metodę, parametr lub wartość zwracaną.
Aby jawnie zidentyfikować element docelowy atrybutu, użyj następującej składni:
[target : attribute-list]
W poniższej tabeli przedstawiono listę możliwych wartości target
.
Wartość docelowa | Dotyczy |
---|---|
assembly |
Cały montaż |
module |
Bieżący moduł montażu |
field |
Pole w klasie lub w strukturze |
event |
Zdarzenie |
method |
Metoda lub get i set metody dostępu do właściwości |
param |
Parametry metody lub parametry akcesora właściwości set |
property |
Własność |
return |
Zwracana wartość metody, indeksatora właściwości lub get akcesora właściwości |
type |
Struktura, klasa, interfejs, wyliczenie lub delegat |
Można określić wartość docelową field
, aby zastosować atrybut do pomocniczego pola utworzonego dla automatycznie zaimplementowanej właściwości .
W poniższym przykładzie pokazano, jak zastosować atrybuty do zestawów i modułów. Aby uzyskać więcej informacji, zobacz Common attributes (C#).
using System;
using System.Reflection;
[assembly: AssemblyTitleAttribute("Production assembly 4")]
[module: CLSCompliant(true)]
W poniższym przykładzie pokazano, jak zastosować atrybuty do metod, parametrów metody i zwracanych wartości metody w języku 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; }
Uwaga
Niezależnie od obiektów docelowych, dla których atrybut ValidatedContract
jest zdefiniowany jako prawidłowy, należy określić obiekt docelowy return
, nawet jeśli atrybut ValidatedContract
jest zdefiniowany w celu zastosowania tylko do zwracanych wartości. Innymi słowy, kompilator nie używa informacji AttributeUsage
do rozpoznawania niejednoznacznych obiektów docelowych atrybutów. Aby uzyskać więcej informacji, zobacz AttributeUsage.
Przejrzyj sposoby używania atrybutów
Oto kilka typowych sposobów używania atrybutów w kodzie:
- Oznacz metody kontrolera, które odpowiadają na komunikaty POST przy użyciu atrybutu
HttpPost
. Aby uzyskać więcej informacji, zobacz klasę HttpPostAttribute. - Opisz, jak zarządzać parametrami metody podczas współpracy z kodem natywnym. Aby uzyskać więcej informacji, zobacz klasę MarshalAsAttribute.
- Opis właściwości modelu obiektów składników (COM) dla klas, metod i interfejsów.
- Wywołaj kod niezarządzany przy użyciu klasy DllImportAttribute.
- Opisz zestaw pod względem tytułu, wersji, opisu lub znaku towarowego.
- Opisz, którzy członkowie klasy powinni być zserializowani w celu zapewnienia trwałości.
- Opis sposobu mapowania między elementami członkowskimi klasy i węzłami XML na potrzeby serializacji XML.
- Opisz wymagania dotyczące zabezpieczeń metod.
- Określ właściwości używane do wymuszania zabezpieczeń.
- Optymalizacja sterowania za pomocą kompilatora just in time (JIT), dzięki czemu kod pozostaje łatwy do debugowania.
- Uzyskaj informacje o obiekcie wywołującym metodę.
Przeglądanie scenariuszy refleksji
Refleksja jest przydatna w następujących scenariuszach:
- Dostęp do atrybutów w metadanych programu. Aby uzyskać więcej informacji, zobacz Pobieranie informacji przechowywanych w atrybutach.
- Badanie i tworzenie wystąpień typów w zestawie.
- Twórz nowe typy w czasie wykonywania przy użyciu klas w przestrzeni nazw System.Reflection.Emit.
- Wykonaj metody późnego powiązania i dostępu dla typów utworzonych w czasie wykonywania. Aby uzyskać więcej informacji, zobacz Dynamiczne ładowanie i używanie typów.