Доступ к пользовательским атрибутам
После того как с элементами программы связаны атрибуты, можно использовать отражение для проверки их существования и получения значений. В .NET Framework версии 1.0 и 1.1 пользовательские атрибуты проверяются в контексте выполнения. Платформа .NET Framework версии 2.0 предоставляет новый контекст загрузки — контекст только для отражения, который может быть использован для проверки кода, который не может быть загружен для выполнения.
Контекст только для отражения
Код, загруженный в контекст только для отражения, не может быть выполнен. Это означает, что экземпляры пользовательских атрибутов не могут быть созданы, потому что это потребует выполнения соответствующих конструкторов. Чтобы загрузить и просмотреть пользовательские атрибуты в контексте только для отражения, используйте класс CustomAttributeData. Можно получить экземпляры этого класса посредством использования допустимой перегрузки статического метода CustomAttributeData.GetCustomAttributes. См. раздел Практическое руководство. Загрузка сборок в контекст, предназначенный только для отражения.
Контекст выполнения
Основные методы отражения, используемые для запроса атрибутов в контексте выполнения — это MemberInfo.GetCustomAttributes и Attribute.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(...)
{
}
}
Если среда выполнения пытается получить пользовательские атрибуты для открытого типа пользовательского атрибута DescriptionAttribute, присоединенного к методу GetLanguage, она пытается выполнить следующие действия:
Среда выполнения проверяет, является ли аргумент типа DescriptionAttribute для метода Type.GetCustomAttributes(Type type) открытым и, следовательно, видимым и доступным.
Среда выполнения проверяет, является ли определенный пользователем тип MyDescriptionAttribute, производный из DescriptionAttribute, видимым и доступным в сборке System.Web.DLL, в которой он назначается методу GetLanguage().
Среда выполнения проверяет, является ли конструктор атрибута MyDescriptionAttribute видимым и доступным в сборке System.Web.DLL .
Среда выполнения вызывает конструктор атрибута MyDescriptionAttribute с параметрами пользовательского атрибута и возвращает в вызывающий код новый объект.
Модель отражения пользовательских атрибутов может создать экземпляры определенного пользователем типа вне сборки, в которой этот тип определен. Возникает та же ситуация, что и в случае элементов в системной библиотеке среды выполнения, которые возвращают экземпляры определенных пользователем типов, как, например, метод Type.GetMethods() возвращает массив объектов RuntimeMethodInfo. Чтобы клиент не смог получить сведения о типе атрибута, определенном пользователем, следует описать элементы этого типа как неоткрытые.
В следующем примере показан простейший способ использования отражения для получения доступа к пользовательским атрибутам.
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