.Net Tips – Restricting attribute usage to specific type

Yan Cui

I help clients go faster for less using serverless technologies.

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

 

Whenever you’re ready, here are 4 ways I can help you:

  1. If you want a one-stop shop to help you quickly level up your serverless skills, you should check out my Production-Ready Serverless workshop. Over 20 AWS Heroes & Community Builders have passed through this workshop, plus 1000+ students from the likes of AWS, LEGO, Booking, HBO and Siemens.
  2. If you want to learn how to test serverless applications without all the pain and hassle, you should check out my latest course, Testing Serverless Architectures.
  3. If you’re a manager or founder and want to help your team move faster and build better software, then check out my consulting services.
  4. If you just want to hang out, talk serverless, or ask for help, then you should join my FREE Community.

 


1 thought on “.Net Tips – Restricting attribute usage to specific type”

  1. Hay Great…

    Thanks for sharing this great tips with us. This will relay help a developer to build an application easily.

    So, please keep updates in it.

Leave a Comment

Your email address will not be published. Required fields are marked *