.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;
    }
}
Liked this article? Support me on Patreon and get direct help from me via a private Slack channel or 1-2-1 mentoring.
Subscribe to my newsletter


Hi, I’m Yan. I’m an AWS Serverless Hero and the author of Production-Ready Serverless.

I specialise in rapidly transitioning teams to serverless and building production-ready services on AWS.

Are you struggling with serverless or need guidance on best practices? Do you want someone to review your architecture and help you avoid costly mistakes down the line? Whatever the case, I’m here to help.

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, callbacks, nested workflows, design patterns and best practices.

Get Your Copy