How to create a Custom Attribute?

Asked

Viewed 457 times

7

For some time I’ve been trying to understand the concept of custom attribute of C#. I think it kind of looks like the system of decorators from Python. But I’m not getting it very well.

I read in a article Codeproject, but it is not yet clear. I understood that to create a CustomAttribute, it is necessary to create a class that inherits from Attribute. But let’s say I want to create a CustomAttribute to validate the type property int of a class, to allow only even numbers. In this case where would be the validation code?

An example would be nice.

1 answer

5


First there is a mistake in thinking that the attributes of C# are equivalent to decorators of Python, the operation of both are quite different.

The attribute is just static information, it’s a metadata. If they are not called by some mechanism they do nothing. This call is made through reflection (example), so it differs from Python.

Of course, it is possible to use this mechanism to facilitate the creation of a Decorator. In fact this is done in a question in the OS. One direct comparison with Python is made here.

You can create a method in the attribute to perform the validation itself, but it will not be done just because the attribute is present in some element of the code. Your invocation will be at some other location, made by the user attribute programmer or by some framework that automates this for the final programmer. That answer shows this well.

Has a example of how it works and one more complete in the Codeproject. The .NET has an example well complete of how it can be a similar attribute (note that the IsValid() is not called alone, just like the other methods of the class).

Your example:

[TypeUsage(int)] //atributo hipotético
class EvenAttribute : Attribute {
    public string Message { get; set; }
    public bool IsValid(int value) {
        return value % 2 == 0;
    }
}

I put in the Github for future reference.

This hypothetical attribute TypeUsage which can be used by some tool to ensure that your custom attribute is only used in a property of type int. This attribute would need to be created by you and the checking tool as well.

Obviously, as the examples show linked above, it is possible to do something more sophisticated, it can be something within a larger mechanism, with specific contracts established, it depends on the need, but generally this is the example.

Practical example of use in another question.

  • My idea was to create something automatic, where I treat in only one place and the effect applies to any created object, leaving the treatment transparent to those who consume the class, ie, any class that "decorates" a property type int with the Attribute TypeUsage and when an object of this class is instantiated with a nonpar value, an exception would be thrown. But this should be transparent to the consumer of the class, he should not need to treat. I could use the get and set patterns, but what if I needed the same effect in several other classes, I would have to repeat code.

  • My experience is that this does not always work as desired except in simple or flexible systems, unless there are several loopholes, which obviously complicates the mechanism. Automation can be done by a method that deals with this, in general, to be transparent, will be by creating a framework. I guess I shouldn’t have used the TypeUsage, you don’t understand his function there, he’s an attribute used in the creation of another attribute. Pretend it doesn’t exist until you understand the rest. Make an exception? Okay, okay, it’s an option, but I probably wouldn’t do this.

  • It may be transparent to the consumer class that uses the attribute, but the call to execute the validation needs to occur somewhere, so it is often used in frameworks that make things kind of "magical" as you want. Maybe you need to think of a more concrete case than you want and ask another question.

  • No, not what I need is exactly that. I already do this in python through metaclasses. There I have several classes with attributes that cannot be negative. There the treatment is within a metaclass, so all classes that need the treatment make use of the metaclass I created. Thus avoiding code replication. I thought the C# Customattribute feature would allow me to do something similar.

  • A correction, in the first commit I erroneously quoted "Attribute Typeusage" when in fact it is Attibute EvenAttribute

  • It helps, but not alone. You would need to create the mechanism similar to that of metaclasses on your own or use some framework ready to do it for you.

  • Do you know me any? Preferably MS

  • It depends on what you need. ASP.Net MVC makes this very automatic.

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.