Accessing Custom Attributes

After attributes have been associated with program elements, reflection can be used to query their existence and values. The main reflection methods to query attributes are contained in System.Reflection.MemberInfo.GetCustomAttributes and System.Reflection.Assembly.GetCustomAttributes.

The accessibility of a custom attribute is checked with respect to the assembly in which it is attached. This is equivalent to checking whether a method on a type in the assembly in which the custom attribute is attached can call the constructor of the custom attribute.

Methods such as System.Reflection.Assembly.GetCustomAttributes(Type, Boolean) check the visibility and accessibility of the type argument. Only code in the assembly that contains the user-defined type can retrieve a custom attribute of that type using GetCustomAttributes.

The following example is a typical custom attribute design pattern. It illustrates the runtime custom attribute reflection model.

System.DLL
public class DescriptionAttribute : Attribute
{
}

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

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

If the runtime is attempting to retrieve the custom attributes for the public custom attribute type DescriptionAttribute attached to the GetLanguage method, it performs the following actions:

  1. The runtime checks that the type argument DescriptionAttribute to Type.GetCustomAttributes(Type type) is public, and therefore is visible and accessible.
  2. The runtime checks that the user-defined type MyDescriptionAttribute that is derived from DescriptionAttribute is visible and accessible within the System.Web.DLL assembly, where it is attached to the method GetLanguage().
  3. The runtime checks that the constructor of MyDescriptionAttribute is visible and accessible within the System.Web.DLL assembly.
  4. The runtime calls the constructor of MyDescriptionAttribute with the custom attribute parameters and returns the new object to the caller.

The custom attribute reflection model could leak instances of user-defined types outside the assembly in which the type is defined. This is no different from the members in the runtime system library that return instances of user-defined types, such as Type.GetMethods() returning an array of RuntimeMethodInfo objects. To prevent a client from discovering information about a user-defined custom attribute type, define the type's members to be nonpublic.

The following example demonstrates the basic way of using reflection to get access to custom attributes.

Class MainClass
    Public Shared Sub Main()
        Dim info As System.Reflection.MemberInfo = GetType(Class1)
        Dim attributes As Object() = info.GetCustomAttributes(True)
        Dim i As Integer
        For i = 0 To attributes.Length - 1
            System.Console.WriteLine(attributes(i))
        Next i
    End Sub
End Class
[C#]class MainClass 
{ 
public static void Main() 
{
    System.Reflection.MemberInfo info = typeof(MyClass);
    object[] attributes = info.GetCustomAttributes();
    for (int i = 0; i < attributes.Length; i ++)
        {
        System.Console.WriteLine(attributes[i]);
        }
    }
}

See Also

Viewing Type Information | Attributes Tutorial | MemberInfo.GetCustomAttributes | Attributes.GetCustomAttributes | Security Considerations for Reflection