This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

.NET 2.0+

Reflecting Attributes

The twenty-first part of the Reflection tutorial looks at the reflection of attributes. Attributes are used to decorate assemblies, types, members and other code to provide metadata about those items. With reflection, this metadata can be accessed.

Retrieving Inherited Attributes

Some, but not all, attributes can be applied to a base class and be automatically inherited by subclasses. The DebuggerDisplay attribute is one such type, though Serializable is not. However, if we use the code we've tried so far against the Employee class, we find that the attributes from the Employee superclass are not retrieved:

Type type = typeof(Employee);
object[] attributes = type.GetCustomAttributes(false);
Console.WriteLine(attributes.Length);   // 0

To get the inherited attributes we need to use the Boolean parameter that we've ignored thus far. This is a flag that tells the GetCustomAttributes method whether or not inherited attributes should be included in the search. When we set it to true, the DebuggerDisplay attribute is found, as you can see in the following sample. Note that only one attribute is returned because Serializable is not passed from superclass to subclass.

Type type = typeof(Employee);
object[] attributes = type.GetCustomAttributes(true);
Console.WriteLine(attributes.Length);   // 1

Reflecting Assembly Attributes

Although the Assembly type is not derived from MemberInfo, it does have a GetCustomAttributes method, so you can obtain details of an assembly's attributes in the same manner. This is demonstrated by the code below, which shows some of the attribute types that an assembly is given by default.

Assembly assembly = Assembly.GetExecutingAssembly();
object[] attributes = assembly.GetCustomAttributes(false);
foreach (object attribute in attributes)




Reflecting Attributes with Attribute Static Methods

Another option for retrieving attributes is using static methods from the Attribute class. To recreate the functionality we've already seen we can use the GetCustomAttributes method. For its first argument, you should pass the item that you wish to examine. You can optionally supply the type of attribute to find if you wish to filter the results. For the final argument, pass the Boolean value that specifies whether inherited attributes should be included in the results.

One minor difference in the static version of the method is that the results are provided as an array of Attributes, rather than plain objects:

Assembly assembly = Assembly.GetExecutingAssembly();
Attribute[] attributes
    = Attribute.GetCustomAttributes(assembly, typeof(AssemblyFileVersionAttribute));
AssemblyFileVersionAttribute attribute = (AssemblyFileVersionAttribute)attributes[0];



Obtaining a Specific Attribute

If you are looking for a specific attribute and you expect that it will only be defined once for the item being examined, use the GetCustomAttribute method. The provided arguments are the item to be examined and the type of attribute to find. The final parameter is optional. It determines whether inherited attributes are included. The method returns an Attribute instance if the item is found and null if it is not. If the attribute is defined more than once, an exception will be thrown. If this is a possibility, you should use the GetCustomAttributes method to get all instances of the attribute type.

The code below retrieves the executing assembly's AssemblyFileVersion attribute and displays its Version property value.

Assembly assembly = Assembly.GetExecutingAssembly();
Attribute attribute
    = Attribute.GetCustomAttribute(assembly, typeof(AssemblyFileVersionAttribute));
var fviAttr = (AssemblyFileVersionAttribute)attribute;



Checking if an Attribute Exists

When you only need to know whether an attribute is defined for a member, and you aren't interested in its properties, you can perform a basic check with the IsDefined method. The arguments are used to provide the item being examined and the type of attribute to find. By default, inherited attributes are not included in the search. You can add a third, Boolean parameter with a value of true to include them. The method returns true if the attribute is found and false otherwise.

Type type = typeof(Person);
bool defined = Attribute.IsDefined(type, typeof(SerializableAttribute));    // true
17 August 2012