Uzyskiwanie dostępu do atrybutów niestandardowych

Po skojarzeniu atrybutów z elementami programu odbicie może służyć do wykonywania zapytań dotyczących ich istnienia i wartości. Platforma .NET udostępnia element MetadataLoadContext, którego można użyć do zbadania kodu, którego nie można załadować do wykonania.

MetadataLoadContext

Nie można wykonać kodu załadowanego do MetadataLoadContext kontekstu. Oznacza to, że nie można utworzyć wystąpień atrybutów niestandardowych, ponieważ wymagałoby to wykonywania ich konstruktorów. Aby załadować i zbadać atrybuty niestandardowe w MetadataLoadContext kontekście, użyj CustomAttributeData klasy . Wystąpienia tej klasy można uzyskać przy użyciu odpowiedniego przeciążenia metody statycznej CustomAttributeData.GetCustomAttributes . Aby uzyskać więcej informacji, zobacz How to: Inspect assembly contents using MetadataLoadContext (Instrukcje: sprawdzanie zawartości zestawu przy użyciu elementu MetadataLoadContext).

Kontekst wykonywania

Główne metody odbicia atrybutów zapytania w kontekście wykonywania to MemberInfo.GetCustomAttributes i Attribute.GetCustomAttributes.

Dostępność atrybutu niestandardowego jest sprawdzana w odniesieniu do zestawu, w którym jest dołączony. Jest to równoważne sprawdzaniu, czy metoda w typie w zestawie, w którym jest dołączony atrybut niestandardowy, może wywołać konstruktor atrybutu niestandardowego.

Metody, takie jak Assembly.GetCustomAttributes(Boolean) sprawdzanie widoczności i dostępności argumentu typu. Tylko kod w zestawie zawierający typ zdefiniowany przez użytkownika może pobrać atrybut niestandardowy tego typu przy użyciu polecenia GetCustomAttributes.

Poniższy przykład w języku C# jest typowym wzorcem projektowania atrybutów niestandardowych. Ilustruje model odbicia atrybutu niestandardowego środowiska uruchomieniowego.

System.DLL
public class DescriptionAttribute : Attribute
{
}

System.Web.DLL
internal class MyDescriptionAttribute : DescriptionAttribute
{
}

public class LocalizationExtenderProvider
{
    [MyDescriptionAttribute(...)]
    public CultureInfo GetLanguage(...)
    {
    }
}

Jeśli środowisko uruchomieniowe próbuje pobrać atrybuty niestandardowe dla publicznego typu DescriptionAttribute atrybutu niestandardowego dołączonego do GetLanguage metody, wykonuje następujące akcje:

  1. Środowisko uruchomieniowe sprawdza, czy argument DescriptionAttributeType.GetCustomAttributes(Type type) typu jest publiczny i dlatego jest widoczny i dostępny.
  2. Środowisko uruchomieniowe sprawdza, czy typ MyDescriptionAttribute zdefiniowany przez użytkownika, z którego pochodzi DescriptionAttribute , jest widoczny i dostępny w zestawie System.Web.dll, gdzie jest dołączony do metody GetLanguage().
  3. Środowisko uruchomieniowe sprawdza, czy konstruktor obiektu MyDescriptionAttribute jest widoczny i dostępny w zestawie System.Web.dll.
  4. Środowisko uruchomieniowe wywołuje konstruktor MyDescriptionAttribute z parametrami atrybutu niestandardowego i zwraca nowy obiekt do obiektu wywołującego.

Model odbicia atrybutu niestandardowego może wyciekać wystąpień typów zdefiniowanych przez użytkownika poza zestawem, w którym jest zdefiniowany typ. Nie różni się to od elementów członkowskich w bibliotece systemu środowiska uruchomieniowego, które zwracają wystąpienia typów zdefiniowanych przez użytkownika, takich jak Type.GetMethods zwracanie tablicy RuntimeMethodInfo obiektów. Aby uniemożliwić klientowi odnajdywanie informacji o typie atrybutu niestandardowego zdefiniowanego przez użytkownika, zdefiniuj elementy członkowskie typu jako niepubliczne.

W poniższym przykładzie przedstawiono podstawowy sposób używania odbicia w celu uzyskania dostępu do atrybutów niestandardowych.

using namespace System;

public ref class ExampleAttribute : Attribute
{
private:
    String^ stringVal;

public:
    ExampleAttribute()
    {
        stringVal = "This is the default string.";
    }


    property String^ StringValue
    {
        String^ get() { return stringVal; }
        void set(String^ value) { stringVal = value; }
    }
};

[Example(StringValue="This is a string.")]
public ref class Class1
{
public:
    static void Main()
    {
        System::Reflection::MemberInfo^ info = Type::GetType("Class1");
        for each (Object^ attrib in info->GetCustomAttributes(true))
        {
            Console::WriteLine(attrib);
        }
    }
};

int main()
{
    Class1::Main();
}
using System;

public class ExampleAttribute : Attribute
{
    private string stringVal;

    public ExampleAttribute()
    {
        stringVal = "This is the default string.";
    }

    public string StringValue
    {
        get { return stringVal; }
        set { stringVal = value; }
    }
}

[Example(StringValue="This is a string.")]
class Class1
{
    public static void Main()
    {
        System.Reflection.MemberInfo info = typeof(Class1);
        foreach (object attrib in info.GetCustomAttributes(true))
        {
            Console.WriteLine(attrib);
        }
    }
}
Public Class ExampleAttribute
    Inherits Attribute

    Private stringVal As String

    Public Sub New()
        stringVal = "This is the default string."
    End Sub

    Public Property StringValue() As String
        Get
            Return stringVal
        End Get
        Set(Value As String)
            stringVal = Value
        End Set
    End Property
End Class

<Example(StringValue:="This is a string.")> _
Class Class1
    Public Shared Sub Main()
        Dim info As System.Reflection.MemberInfo = GetType(Class1)
        For Each attrib As Object In info.GetCustomAttributes(true)
            Console.WriteLine(attrib)
        Next attrib
    End Sub
End Class

Zobacz też