.Net Tips – Restricting attribute usage to specific type

Before you get your hopes up, sorry, there’s no built-in support to allow you to restrict the usage of your attribute to a type easily. That’s not to say that it’s impossible though!

If you’re reading this, I assume that you’ve tried to write a custom attribute yourself and realised that the options available in the AttributeTargets enum is fairly limited.

For those of you who are familiar with PostSharp, you would probably have noticed that one of the methods you can override is curiously called CompileTimeValidate and returns a boolean value. You can use the MethodBase argument passed into this method to inspect the type the attribute has been applied to and perform some validation logic there, e.g.:

[Serializable]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Method)]
public class MyAttribute : OnMethodBoundaryAspect
{
    public override bool CompileTimeValidate(System.Reflection.MethodBase method)
    {
        var type = method.DeclaringType;

        // if the attribute is used outside the Service class, fail the build
        if (!type.Equals(typeof(Service)))
        {
            throw new Exception("MyAttribute can only be used in the Service class");
        }

        return true;
    }
}

Because you have the metadata for the method in hand, there’s nothing to stop you from restricting the usage of your attribute by input and return types too, e.g. attribute can only be applied to a method which returns string, etc.

If this is too much work for your liking, Marc Gravell blogged about a neat trick you could do to achieve the same effect here. The trick exploits the protected modifier in C# so that an attribute declared in the base type can be used by derived types but not by others. Here’s the code snippet from his original post:

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; }
}

Update: I saw another related question on StackOverflow here, as far as I’m aware you won’t be able to do this without the help of PostSharp as you won’t have access to the access modifiers (public, protected, internal or private) that was applied to the field when it was declared. With PostSharp however, this is how you would could go about doing such validation at compile time and make sure the attribute is applied to a public or protected field:

[Serializable]
[AttributeUsage(AttributeTargets.Field)]
public class MyAttribute : OnFieldAccessAspect
{
    public override bool CompileTimeValidate(System.Reflection.FieldInfo field)
    {
        if (field.IsPublic || field.IsFamily)
        {
            throw new Exception("Attribute can only be applied to Public or Protected fields");
        }

        return true;
    }
}

Enjoy what you’re reading? Subscribe to my newsletter and get more content on AWS and serverless technologies delivered straight to your inbox.


Yan Cui

I’m an AWS Serverless Hero and the author of Production-Ready Serverless. I have run production workload at scale in AWS for nearly 10 years and I have been an architect or principal engineer with a variety of industries ranging from banking, e-commerce, sports streaming to mobile gaming. I currently work as an independent consultant focused on AWS and serverless.

You can contact me via Email, Twitter and LinkedIn.

Hire me.


Check out my new course, Complete Guide to AWS Step Functions.

In this course, we’ll cover everything you need to know to use AWS Step Functions service effectively. Including basic concepts, HTTP and event triggers, activities, design patterns and best practices.

Get Your Copy