Generic Attributes in C#

As awesome as C# is, once you want to do some more advanced stuff with attributes, you quickly run into several limitations. There is even a Microsoft Connect entry on this issue.

  • Attributes can’t be generic, since a generic type cannot derive from ‘Attribute’.
  • An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type.

Using TypeDescriptor and a whole bunch of custom code these limitations can be overcome. In this post I will describe an easier straightforward way by which to create something similar to generic attributes, ignoring the second issue for now. In future posts I will discuss how and where these attributes can be used for something I previously called attribute metabehavior.

The idea is quite straightforward; although attributes can’t be generic, nothing prevents you from adding generic instances to them. These instances can later be extracted at run time using reflection. The trick of course is initializing the generic instance. Once you know the Activator class can create instances by knowing their Type definition, the solution becomes self-evident. By simply passing the generic type as an argument to the attribute, instance creation can be delegated to Activator. Optional constructor arguments can also be passed as attribute arguments.

public class BehaviorAttribute : Attribute
{
	/// <summary>
	///   The dynamically created instance of the type passed to the constructor.
	/// </summary>
	public object DynamicInstance { get; private set; }

	/// <summary>
	///   Create a new attribute and initialize a certain type.
	/// </summary>
	/// <param name = "dynamicType">The type to initialize.</param>
	/// <param name = "constructorArguments">
	///   The arguments to pass to the constructor of the type.
	/// </param>
	public BehaviorAttribute(
		Type dynamicType,
		params object[] constructorArguments )
	{
		DynamicInstance =
			Activator.CreateInstance( dynamicType, constructorArguments );
	}
}

This attribute can then be be applied as follows:

class Answer<T>
{
	public T Value;

	public Answer( T value )
	{
		Value = value;
	}
}

[BehaviorAttribute( typeof( Answer<int> ), 42 )]
class TheWorld {}

Using ordinary reflection, the instance can be extracted.

Type type = typeof( TheWorld );
var behavior = (BehaviorAttribute)type
    .GetCustomAttributes( typeof( BehaviorAttribute ), false ).First());
var genericInstance = (Answer<int>)behavior.DynamicInstance;
int answer = genericInstance.Value;

What follows is up to you, how will you use this? I’ll describe a few advanced use cases in subsequent posts.

Author: Steven Jeuris

I have a PhD in Human-Computer Interaction and am currently working both as a software engineer at iMotions and as a postdoc at the Technical University of Denmark (DTU). This blend of research and development is the type of work which motivates and excites me the most. Currently, I am working on a distributed platform which enables researchers to conduct biometric research 'in the wild' (outside of the lab environment). I have almost 10 years of professional software development experience. Prior to academia, I worked for several years as a professional full-stack software developer at a game development company in Belgium: AIM Productions. I liked the work and colleagues at the company too much to give up entirely for further studies, so I decided to combine the two. In 2009 I started studying for my master in Game and Media Technology at the University of Utrecht in the Netherlands, from which I graduated in 2012.

9 thoughts on “Generic Attributes in C#”

  1. Hello,

    That help me a lot, but i have a question. If the Attribue property is a “struct” like “Color” ?

    Here my example :

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
    public class TableAttribute : Attribute {
    public bool HasBorder;

    public System.Windows.Forms.HorizontalAlignment HeaderTextAlign;
    public Color? HeaderBackColor;
    public Color? HeaderForeColor;
    public Font HeaderFont;

    public System.Windows.Forms.HorizontalAlignment TextAlign;
    public Color? BackColor;
    public Color? ForeColor;
    public Font Font;
    }

    FYI this Class Attribute help me to generate “table” in lot of format (html, word, jpeg …).

    1. Your question is unclear, but I suppose you are stuck trying to initialize a Color from within the Attribute definition? This is not possible due to the second restriction I listed. You will need to do some kind of conversion in the constructor instead and thus a general solution won’t be possible. One possibility is passing 4 int arguments representing ARGB. I’m still exploring a more general approach to initializing such objects, but it will always need to rely on a similar implementation. A general solution could involve some sort of parser, aware about all the basic FCL types.

  2. Hi there, thanks for the info.
    Personaly I’m on an Asp.Net Mvc4 proyect.
    I’m trying to do something like this on my Secure, so I donot have to deploy everytime that some new role is added to my app.

    [Authorize()]
    [Secure(Roles = WebUI.Controllers.ActionController.Ver() )]
    public class ActionController : Controller
    {

    public static string Ver(){
    return “Developers”;
    }

    And I get this….

    Error 1 An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type

    1. ….. soooo, what is your question? I presume you gave the answer yourself? “An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type”?

      1. Thats the deal…. I had tey const, and didnot work. Ans ot cant be a const. I need it to be method so I can retrive from my db how has access tp this controller.
        Thanks.

      1. Oh. I meant the “future posts” that describes this post.

        “In future posts I will discuss how and where these attributes can be used for something I previously called attribute metabehavior.”

    1. Oh, my bad. Seems like I didn’t read your question properly. I believe I used them in my WPF framework, but seemingly so far have only shortly referred to them at the end of my post on ‘attribute metabehavior’.

      I can point you to the exact source code where I used such generic ‘attribute metabehavior’. I have two unit tests which showcase it here, which use such attributes to implement coercion and validation in WPF user controls. Most of the complex initialization logic is pushed down in abstract classes, so you will have to trace the logic there in case you are interested in doing something similar. Source code of some actual attributes is here.

      E.g., you can see there is a `RegexValidationAttribute` and more interestingly a `RangeCoercionAttribute` which takes care of otherwise quite complicated (yet redundant code bloat) implementations.

      Non of this can work ‘out-of-the-box’, it relies on a lot of underlying complex behavior (some of which I blogged about in the past) which depends on other classes in my core library. `RangeCoercienAttribute` extends from `CoercionHandlerAttribute` which takes core of the generic initialization by using a non-generic proxy which is generated at runtime (blogged about that here) (quite experimental, but working for the specified use cases). It seems like I never put time aside to try to make a ‘minimum working’ example as a separate post although that was my original intent.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s