访问自定义特性

当特性与程序元素相关联后,可以使用反射来查询它们是否存在以及它们的值。 在 .NET Framework 1.0 和 1.1 版中,是在执行上下文中检查自定义特性。 .NET Framework 2.0 版提供了新的加载上下文(只反射上下文),该上下文可用于检查无法加载执行的代码。

只反射上下文

加载到只反射上下文中的代码无法执行。 这意味着不能创建自定义特性的实例,因为这将需要执行其构造函数。 若要在只反射上下文中加载和检查自定义特性,请使用 CustomAttributeData 类。 可以通过使用静态 CustomAttributeData.GetCustomAttributes 方法的相应重载获取此类的实例。 请参见如何:将程序集加载到仅反射上下文中

执行上下文

用于查询执行上下文中的特性的主要反射方法是 MemberInfo.GetCustomAttributesAttribute.GetCustomAttributes

自定义特性的可访问性根据附加该特性的程序集来进行检查。 这相当于检查附加自定义特性的程序集中,其类型的方法是否可以调用自定义特性的构造函数。

诸如 Assembly.GetCustomAttributes(Boolean) 等方法检查类型参数的可见性和可访问性。 只有包含用户定义类型的程序集中的代码才能使用 GetCustomAttributes 检索该类型的自定义特性。

下面的 C# 示例是典型的自定义特性设计模式。 它说明运行时自定义特性反射模型。

System.DLL
public class DescriptionAttribute : Attribute
{
}

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

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

如果运行时尝试为附加到 GetLanguage 方法的公共自定义特性类型 DescriptionAttribute 检索自定义特性,则该运行时将执行下列操作:

  1. 运行时检查 Type.GetCustomAttributes(Type type) 的 DescriptionAttribute 类型参数是否为公共的,从而是否可见和访问。

  2. 运行时检查从 DescriptionAttribute 派生的用户定义类型 MyDescriptionAttributeSystem.Web.DLL 程序集(它在该程序集中附加到 GetLanguage() 方法)内是否可见和可以访问。

  3. 运行时检查 MyDescriptionAttribute 的构造函数是否在 System.Web.DLL 程序集中可见和可以访问。

  4. 运行时调用带有自定义特性参数的 MyDescriptionAttribute 的构造函数,然后将新对象返回给调用方。

自定义特性反射模型可能会在定义类型的程序集外泄漏用户定义类型的实例。 这与运行时系统库中返回用户定义类型的实例的成员(例如返回 RuntimeMethodInfo 对象数组的 Type.GetMethods())相同。 为了防止客户端发现关于用户定义的自定义特性类型的信息,请将该类型的成员定义为非公共成员。

下面的示例说明使用反射访问自定义特性的基本方法。

Imports System

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
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);
        }
    }
}
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();
}

请参见

参考

MemberInfo.GetCustomAttributes

Attribute.GetCustomAttributes

概念

查看类型信息

反射的安全注意事项