How to Create a Custom Attribute in C#

How to create a custom attribute in C#

While the code to create a custom Attribute is fairly simple, it's very important that you understand what attributes are:

Attributes are metadata compiled into your program. Attributes themselves do not add any functionality to a class, property or module - just data. However, using reflection, one can leverage those attributes in order to create functionality.

So, for instance, let's look at the Validation Application Block, from Microsoft's Enterprise Library. If you look at a code example, you'll see:

    /// <summary>
/// blah blah code.
/// </summary>
[DataMember]
[StringLengthValidator(8, RangeBoundaryType.Inclusive, 8, RangeBoundaryType.Inclusive, MessageTemplate = "\"{1}\" must always have \"{4}\" characters.")]
public string Code { get; set; }

From the snippet above, one might guess that the code will always be validated, whenever changed, accordingly to the rules of the Validator (in the example, have at least 8 characters and at most 8 characters). But the truth is that the Attribute does nothing; as mentioned previously, it only adds metadata to the property.

However, the Enterprise Library has a Validation.Validate method that will look into your object, and for each property, it'll check if the contents violate the rule informed by the attribute.

So, that's how you should think about attributes -- a way to add data to your code that might be later used by other methods/classes/etc.

create custom attribute for class property

This how to access the attributes using Reflection:

(Sure you need to move that to some helper class or something).

static bool Validate<T>(T obj)
{
var properties = obj.GetType().GetProperties().ToList();

foreach(var prop in properties)
{
if(prop.IsDefined(typeof(RequiredAttribute)))
{
object value = prop.GetValue(obj);

if(value == null)
{
// do something
}
}

if(prop.IsDefined(typeof(ContainsNumericAttribute)))
{

}
}

return false; // dummy value now
}

Usage:

MyClass cc = new MyClass()
{
cost = 5
};

Validate(cc); // false, id required

If you want , you can create a validation results object and return it from Validate method add all validations that fails to that object.

C# Custom Attribute parameters

The accepted answer uses the public property instead of a private field. The benefit of public property is you can omit the constructor and supply the values of the properties in the default constructor.

I change your first code, the one with public property, to something like this.

class MyCustomAttribute : Attribute {
public int[] Values { get; set; }
}

[MyCustomAttribute(Values = new int[] { 3, 4, 5 })]
class MyClass { }


Related Topics



Leave a reply



Submit