C#, .Net and Azure

Reflection (2/5) Attributes

2013/01/03

This is the second post in a series. All posts are short excerpts from my Reflection paper.

In the last post we looked into the core of the .Net Framework and how Reflection integrates into it. The result was, that .Net stores information for each type that completely describes the type and is accessible during runtime.

In this post we will look at attributes. Attributes are annotations that enable a programmer to extend the information set of a certain type, method, parameter or assembly.

There are many usecases for attributes.

Examples

Consider unit testing: Most unit testing frameworks (such as MSTest or NUnit) will use attributes on methods to mark them as test methods that should be ran.

Another great example is serialization. Instead of manually reading & parsing text/xml files, the .Net Framework provides Serialization classes that can serialize and deserialize other classes. All that is required is a attribute on each field/property that should be saved/loaded.

Another great example that is often overlooked is the System.Diagnostics.DebuggerDisplayAttribute that is part of the .Net framework.

Usually when displaying a list of objects in the debugger, the view defaults to the full name of the object. Of course one can override the ToString method and thus expose details of the object, but one might find that the debug information that should be displayed differs from the information that the ToString method shows (e.g. ToString should format a business object in a user friendly fashion, while the programmer requires additional internal member states for his debug session).

By using the System.Diagnostics.DebuggerDisplayAttribute he does not need to modify the ToString method and still can view his objects in a nice fashion.

Write your own

Writing your own attributes is incredibly easy: Just create a new class (name it MyFirstAttribute) and derive it from the System.Attribute class. (In .Net it is convention to end a Attribute class with the suffix ‘Attribute’ - when using the attribute, the suffix can be omitted).

[AttributeUsage(AttributeTargets.Mehod, AllowMultiple = false]
public class TestMethodAttribute : Attribute
{
    public string Description { get; set; }
}

Here I just created an attribute that can be applied to methods only (funny how to define where an attribute is valid, you need to apply another attribute to it!) and allowed only one attribte per method.

In the code, it could be used as followed:

public class Test
{
    [TestMethod(Description = "This method adds two numbers")]
    public int Add(int x, int y)
    {
        return x + y;
    }
    
    [TestMethod(Description = "This method multiplies two numbers")]
    public int Mul(int x, int y)
    {
        return x * y;
    }
}

Later at runtime, it is then possible to access these attributes using

var attr = typeof(Test).GetCustomAttributes(typeof (TestMethodAttribute), true);

foreach (var attribute in attr)
{
    Console.WriteLine(typeof(Test).Name + " contains method description: " + ((TestMethodAttribute)attribute).Description);
}

Resulting in the output:

As you can see: Using attributes is an easy and powerful way of adding information to existing objects in .Net. There are many use cases where this is the prefered (or even the only way) to achieve a certain goal.

In the next post, we will look at the dynamic keyword, which is new with .Net 4.0.

tagged as C#, Reflection,