Saturday, 20 June 2009

Restricting attribute usage

.NET attributes are a great way of expressing metadata (when used appropriately), but I regularly see people frustrated that you can't have much control over when you can apply them. Sure, you can use [AttributeUsage] to limit it to any combination of fields, classes, properties, etc - but beyond that... nothing (unless you write an FxCop rule (hard work) or look at PostSharp (still hard work, and changes your build)).

I was looking at this today when somebody wanted to restrict the usage of an attribute just to members in a particular type (inheritance) hierarchy, and I trotted off the usual "sorry, you can't do that" response... but then I went and spoilt it all by proving myself wrong; actually, you can do this - using one of the rarer features in C# - protected classes.

In C#, you are only allowed to use the protected modifier (on a type) on a nested type - and the effect is that only types that inherit from the outer type (and the outer type itself) can see the nested type. And interestingly, it works for attributes! Here's the example I came up with:

abstract class MyBase {
[AttributeUsage(AttributeTargets.Property)]
protected sealed class SpecialAttribute : Attribute {}
}
class ShouldBeValid : MyBase {
[Special] // works fine
public int Foo { get; set; }
}
class ShouldBeInvalid { // not a subclass of MyBase
[Special] // type or namespace not found
[MyBase.Special] // inaccessible due to protection level
public int Bar{ get; set; }
}


An interesting trick...