Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restrict custom attribute so that it can be applied only to Specific types in C#?

I have a custom attribute which is applied to class properties and the class itself. Now all the classes that must apply my custom attribute are derived from a single base class.

How can I restrict my Custom Attribute so that it can be applied to only those classes, that must derive from my base class? How do I do this?

like image 607
this. __curious_geek Avatar asked Jun 20 '09 07:06

this. __curious_geek


People also ask

How would you define a custom attribute that can only be applied to class code elements?

The following code fragment specifies that a custom attribute can be applied to any class or method. [AttributeUsage(AttributeTargets::Class | AttributeTargets::Method)] C# Copy. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] End Class.

How can you specify target for custom attribute?

Which of the following are correct ways to specify the targets for a custom attribute? A. By applying AttributeUsage to the custom attribute's class definition.

What are custom attributes used for?

Custom attributes are attributes that are not part of the standard HTML5 attributes but are explicitly created. They allow us to add our own information to HTML tags. These are not specific and can be used with all the HTML elements.

How would you determine if a class has a particular attribute in C#?

The same you would normally check for an attribute on a class. Here's some sample code. typeof(ScheduleController) . IsDefined(typeof(SubControllerActionToViewDataAttribute), false);


1 Answers

Darn, I hate it when I prove myself wrong... it works if you define the attribute as a protected nested type of the base-class:

abstract class MyBase {
    [AttributeUsage(AttributeTargets.Property)]
    protected sealed class SpecialAttribute : Attribute {}
}

class ShouldBeValid : MyBase {
    [Special]
    public int Foo { get; set; }
}
class ShouldBeInvalid {
    [Special] // type or namespace not found
    [MyBase.Special] // inaccessible due to protection level
    public int Bar{ get; set; }
}

(original answer)

You cannot do this - at least, not at compile time.

Attributes can be restricted (for exmaple) to "class", "struct", "method", "field", etc - but nothing more granular.

Of course, since attributes do nothing by themselves (ignoring PostSharp), they will be inert on other types (and inert on your types unless you add some code to look at the attributes at runtime).

You could write an FxCop rule, but that seems overkill.

I wonder, however, whether an attribute is the best choice:

Now all the classes that must apply my custom attribute are derived from a single base class.

If they must apply your custom attribute, maybe an abstract (or maybe just virtual) property / method would be a better choice?

abstract class MyBase {
    protected abstract string GetSomeMagicValue {get;}
}
class MyActualType : MyBase {
    protected override string GetSomeMagicValue {get {return "Foo";}}
}
like image 173
Marc Gravell Avatar answered Sep 28 '22 22:09

Marc Gravell