What are attributes and why do we need it?
How can we create custom Attributes?
Is it possible to restrict a custom attribute to a method only?
Other than information what more can we do?
What if we want some attributes to be prevented from inheriting?
If I want an attribute to be used only once in a program?
“Attribute is nothing but a piece of information”.
This information can be attached to your method, class, namespace, assembly etc. Attributes are part of your code this makes developers life easier as he can see the information right upfront in the code while he is calling the method or accessing the class and take actions accordingly.
For instance below is a simple class where “Method1” is decorated by the “Obsolete” attribute. Attributes are defined by using the “[]“ symbol. So when developers starting coding in this class they are alerted that“Method1” is obsolete and code should be now written in “NewMethod1”.
1 2 3 4 5 6 7 8 |
<span class="code-keyword" style="color:#0000FF;">public</span> <span class="code-keyword" style="color:#0000FF;">class</span> Class1 { [Obsolete] <span class="code-keyword" style="color:#0000FF;">public</span> <span class="code-keyword" style="color:#0000FF;">void</span> Method1() { } <span class="code-keyword" style="color:#0000FF;">public</span> <span class="code-keyword" style="color:#0000FF;">void</span> NewMethod1() { } } |
In the same way if somebody is trying to create objectof “Class1” he gets an alert in the tool tip as shown in the below code snippet that “Method1” is obsolete and he should use “NewMethod1”.
So in short Attributes are nothing small piece of information which is embedded declaratively in the code itself which developers can see upfront.
In case you want to show some message to the developers you can pass the message in the “Obsolete” attribute as shown in the below code snippet.
1 2 3 4 |
[Obsolete(<span class="code-string" style="color:#800080;">"</span><span class="code-string" style="color:#800080;">Please use NewMethod1"</span>)] <span class="code-keyword" style="color:#0000FF;">public</span> <span class="code-keyword" style="color:#0000FF;">void</span> Method1() { } |
If you want to be bit strict and do not want developers to use that method, you can pass ‘true” to the “Obsolete” attribute as shown in the below code.
1 2 3 4 |
[Obsolete(<span class="code-string" style="color:#800080;">"</span><span class="code-string" style="color:#800080;">Please use NewMethod1"</span>,<span class="code-keyword" style="color:#0000FF;">true</span>)] <span class="code-keyword" style="color:#0000FF;">public</span> <span class="code-keyword" style="color:#0000FF;">void</span> Method1() { } |
Now in case developer tries to make a call to “Method1” they will get error and not just a simple warning.
The “Obsolete” attribute which we discussed at the top is a readymade attribute To create a custom attributes you need to inherit from the attribute class. Below is a simple “HelpAttribute” which has a “HelpText” property.
1 2 3 4 |
<span class="code-keyword" style="color:#0000FF;">class</span> HelpAttribute : Attribute { <span class="code-keyword" style="color:#0000FF;">public</span> string HelpText { get; set; } } |
“HelpAttribute” is applied to the “Customer” as shown in the code below. Now developers who see this class , see the information right in the front of their eyes.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[Help(HelpText=<span class="code-string" style="color:#800080;">"</span><span class="code-string" style="color:#800080;">This is a class"</span>)] <span class="code-keyword" style="color:#0000FF;">class</span> Customer { <span class="code-keyword" style="color:#0000FF;">private</span> string _CustomerCode; [Help(HelpText = <span class="code-string" style="color:#800080;">"</span><span class="code-string" style="color:#800080;">This is a property"</span>)] <span class="code-keyword" style="color:#0000FF;">public</span> string CustomerCode { get { <span class="code-keyword" style="color:#0000FF;">return</span> _CustomerCode; } set { _CustomerCode = <span class="code-keyword" style="color:#0000FF;">value</span>; } } [Help(HelpText = <span class="code-string" style="color:#800080;">"</span><span class="code-string" style="color:#800080;">This is a method"</span>)] <span class="code-keyword" style="color:#0000FF;">public</span> <span class="code-keyword" style="color:#0000FF;">void</span> Add() { } } |
By using the “AttributeUsage” and “AttributeTargets” you can restrict the attribute to a particular section like class , method , property etc. Below is a simple custom attribute is now confined only to methods.
1 2 3 4 |
[AttributeUsage(AttributeTargets.Method)] <span class="code-keyword" style="color:#0000FF;">class</span> HelpAttribute : Attribute { <span class="code-keyword" style="color:#0000FF;">public</span> string HelpText { get; set; } } |
If you try to apply the above attribute over a class or property you would get a compile time error as shown below.
You can also restrict attribute’s to a class , constructor , assembly etc. Below is the list of possibilities to which you can confine your attribute.
One use which we have discussed till now is for the developer’s that they can see the information while coding and take decision accordingly. Other use is you can read the information programmatically using reflection and act on it.
For instance below is a custom attribute which describes length of characters for a property of a class.
1 2 3 |
[AttributeUsage(AttributeTargets.Property)] <span class="code-keyword" style="color:#0000FF;">class</span> Check : Attribute { <span class="code-keyword" style="color:#0000FF;">public</span> <span class="code-keyword" style="color:#0000FF;">int</span> MaxLength { get; set; } } |
Below is a customer class over which that property is decorated providing information that the maximum length of “CustomerCode” property cannot exceed 10 character.
1 2 3 4 5 6 7 8 9 |
<span class="code-keyword" style="color:#0000FF;">class</span> Customer { <span class="code-keyword" style="color:#0000FF;">private</span> string _CustomerCode; [Check(MaxLength = <span class="code-digit" style="color:#000080;">10</span>)] <span class="code-keyword" style="color:#0000FF;">public</span> string CustomerCode { get { <span class="code-keyword" style="color:#0000FF;">return</span> _CustomerCode; } set { _CustomerCode = <span class="code-keyword" style="color:#0000FF;">value</span>; } } } |
Below goes the code which will loop dynamically through the attributes of each property and do the length validation check.
So the first step is to create the object of the customer class.
1 2 |
<span class="code-comment" style="color:#008000;font-style:italic;">//</span><span class="code-comment" style="color:#008000;font-style:italic;"> Create the object of Customer class </span><span class="code-comment" style="color:#008000;font-style:italic;">//</span><span class="code-comment" style="color:#008000;font-style:italic;"> and load it with some data </span>Customer obj = <span class="code-keyword" style="color:#0000FF;">new</span> Customer(); obj.CustomerCode = <span class="code-string" style="color:#800080;">"</span><span class="code-string" style="color:#800080;">12345678901"</span>; |
Second step is to get the “Type” of the object. Because once we get the type of the object we can browse properties, methods etc of the object.
1 |
<span class="code-comment" style="color:#008000;font-style:italic;">//</span><span class="code-comment" style="color:#008000;font-style:italic;"> Get the type of the object </span>Type objtype = obj.GetType(); |
Use the “Type” object and loop through all properties and attributes of those properties.
1 2 3 4 5 |
<span class="code-comment" style="color:#008000;font-style:italic;">//</span><span class="code-comment" style="color:#008000;font-style:italic;"> Loop through all properties </span>foreach (PropertyInfo p <span class="code-keyword" style="color:#0000FF;">in</span> objtype.GetProperties()) { <span class="code-comment" style="color:#008000;font-style:italic;">//</span><span class="code-comment" style="color:#008000;font-style:italic;"> for every property loop through all attributes </span> foreach (Attribute a <span class="code-keyword" style="color:#0000FF;">in</span> p.GetCustomAttributes(<span class="code-keyword" style="color:#0000FF;">false</span>)) { } } |
Once you get hold of the attribute you can do the length check and raise exception accordingly.
1 2 3 4 5 6 7 8 9 10 |
<span class="code-comment" style="color:#008000;font-style:italic;">//</span><span class="code-comment" style="color:#008000;font-style:italic;"> Loop through all properties </span>foreach (PropertyInfo p <span class="code-keyword" style="color:#0000FF;">in</span> objtype.GetProperties()) { <span class="code-comment" style="color:#008000;font-style:italic;">//</span><span class="code-comment" style="color:#008000;font-style:italic;"> for every property loop through all attributes </span> foreach (Attribute a <span class="code-keyword" style="color:#0000FF;">in</span> p.GetCustomAttributes(<span class="code-keyword" style="color:#0000FF;">false</span>)) { Check c = (Check)a; <span class="code-keyword" style="color:#0000FF;">if</span> (p.Name == <span class="code-string" style="color:#800080;">"</span><span class="code-string" style="color:#800080;">CustomerCode"</span>) { <span class="code-comment" style="color:#008000;font-style:italic;">//</span><span class="code-comment" style="color:#008000;font-style:italic;"> Do the length check and and raise exception accordingly </span><span class="code-keyword" style="color:#0000FF;">if</span> (obj.CustomerCode.Length > c.MaxLength) { <span class="code-keyword" style="color:#0000FF;">throw</span> <span class="code-keyword" style="color:#0000FF;">new</span> Exception(<span class="code-string" style="color:#800080;">"</span><span class="code-string" style="color:#800080;"> Max length issues "</span>); } } } } |
Yes, they get inherited in the child classes.
We have an “Inherited” property in “AttributeUsage” if we set it to false those attributes will not be inherited in the child classes.
1 2 3 4 |
[AttributeUsage(AttributeTargets.Property,Inherited=<span class="code-keyword" style="color:#0000FF;">false</span>)] <span class="code-keyword" style="color:#0000FF;">class</span> Check : Attribute { publicintMaxLength { get; set; } } |
If you specify “AllowMultiple” as true it can be used multiple times in the same program.
1 2 3 4 |
[AttributeUsage(AttributeTargets.Property,AllowMultiple=<span class="code-keyword" style="color:#0000FF;">false</span>)] <span class="code-keyword" style="color:#0000FF;">class</span> Check : Attribute { <span class="code-keyword" style="color:#0000FF;">public</span> <span class="code-keyword" style="color:#0000FF;">int</span> MaxLength { get; set; } } |
See the below facebook video which explains and demonstrates C# Attributes practically.
from:http://www.codeproject.com/Articles/827091/Csharp-Attributes-in-minutes#HowcanwecreatecustomAttributes