Custom Attributes
Tuesday, 22 June 2010
Article Index
Custom Attributes
Attribute semantics
Initialising fields
Practical attributes
An example
Solving the practical problems

Practical attributes

Now that we have the basic mechanism that is used to implement attributes out in the open and perfectly clear we need to investigate some of the intricacies of using attributes in a real situation.

Banner

The first thing to say is that you can apply attributes to more than just a class. To restrict what an attribute can be applied to you need to apply the AttributeUsage attribute to the class that is associated with your custom attribute - yes an attribute applied to your custom attribute!

For example:

[AttributeUsage(AttributeTargets.Method)]
public  class ASCII : Attribute

restricts the ASCII attribute to being applied to methods only. If you try to apply it to anything else the compiler will generate an error message. IntelliSense provides a list of AttributeTargets and you can OR targets together to produce a set of things that the attribute can be applied to - an example of this is given later.

Being able to tag other entities with attributes raises the question of how to get at them at runtime?

The answer is that there a number of overloaded versions of GetCustomAttributes which return arrays of attributes associated with different types of entity. For example, GetCustomAttributes(memberinfo) will retrieve an array of attributes applied to the member specified by the memberinfo class. To see how this works first add a member function to MyClass and tag it with the ASCII attribute:

public class MyClass
{
[ASCII("Hello Method")]
public void MyMethod()
{
}
}

To retrieve attributes associated with a member we first have to retrieve its memberinfo. There are many ways of doing this but in most cases specifying it by name is sufficient using the GetMember function:

System.Reflection.MemberInfo[] member =
typeof(MyClass).GetMember("MyMethod");

The GetMember function retrieves all members that match the name specified string which can include wildcard characters. In this case it should just return a memberinfo class corresponding to the unique MyMethod function. To retrieve any attributes applied to the method we can use the usual:

Attribute[] attrs = Attribute.
GetCustomAttributes(member[0]);

Or if you just want the ASCII attributes that have been applied we can use the alternative:

ASCII[] attrs =(ASCII[]) member[0].
GetCustomAttributes(
typeof(ASCII), false);
MessageBox.Show(attrs[0].MyData);

The GetMember function will return members of a range of types – methods, properties etc. You can be more specific if you want to and use functions such as GetMethod to return a single MethodInfo class that is specified by name and other information. For example:

System.Reflection.MethodInfo
method = typeof(MyClass).
GetMethod("MyMethod");
ASCII[] attrs =(ASCII[]) method.
GetCustomAttributes(typeof(ASCII), false);

There is also a GetMethods function which will return an array of methods that match a name that includes wildcard characters. You can return fields, properties, interfaces and so on and use the corresponding GetCustomAttributes to return an array of attributes applied to them.

Retrieving attributes is generally straightforward – use reflection to get the entity and then call GetCustomAttributes.

One slightly more complicated situation is when an attribute is applied to a parameter. In this case we have to first retrieve the method, then the parameters and then the attributes. To see this in action change the ASCII attribute to read:

[AttributeUsage(AttributeTargets.Method |
AttributeTargets.Parameter)]
public  class ASCII : Attribute
{
public string MyData;
public string MoreData;
public ASCII(string MyDataIn)
{
MyData = MyDataIn;
}

Notice that this is an example of OR-ing together parameters used in the constructor call.

The attribute can now be applied to methods and parameters:

public class MyClass
{
[ASCII("Hello Method")]
public void MyMethod(
[ASCII("Hello MyParameter")]
string MyParameter)
{
}
}

To retrieve the attribute we first need to get the method:

System.Reflection.MethodInfo method =
typeof(MyClass).GetMethod("MyMethod");

Then we need to get the parameters of the method:

System.Reflection.ParameterInfo[]
pars= method.GetParameters();

Finally we can get and access the parameter attribute:

ASCII[] attrs = (ASCII[]) pars[0].
GetCustomAttributes(
typeof(ASCII), false);
MessageBox.Show(attrs[0].MyData);

As well as controlling what an attribute can be applied to, you can also control how many times it can be applied using the AttributeUsage attribute and whether or not it is inherited. For example if you change the ASCII class definition to:

[AttributeUsage(AttributeTargets.Method |
AttributeTargets.Parameter,
AllowMultiple=true,Inherited=true )]
public class ASCII : Attribute

you can place multiple attributes on a single entity and the attribute is inherited. For example, following:

[ASCII("Hello Method")]
[ASCII("Hello some more")]
public void MyMethod(string MyParameter)
{
}

GetCustomAttributes will return an array with two instances of ASCII with MyData set to the corresponding string.

Similarly, if you create a new class that inherits from MyClass the attributes are also inherited. For example:

public class MyClass3 : MyClass
{
}

has two ASCII attributes exactly the same as MyClass. You can, of course forbid multiple attributes and stop attribute inheritance by setting the AllowMultiple and Inherited to false.

Banner

<ASIN:1449380344>

<ASIN:0123745144>

<ASIN:0321658701>

<ASIN:0321741765>

<ASIN:0470495995>

<ASIN:0672330792>

<ASIN:0521114292>



Last Updated ( Friday, 27 August 2010 )
 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.