Home > c# > Attributes

Attributes

Following post describes about the attributes in the .net framework.

MSDN says, Attribute is a method of associating declarative information with code entities (i.e. types, methods, properties, and so forth). Attributes add metadata information to program. There are two types of attributes : Pre Defined Attributes and Custom Attributes

Pre Defined Attributes :

These attributes are defined inside the .net framework e.g. Serializable, Obsolete etc.

[Serializable]

public class MyClass

{

public MyClass()

{

}

[Obsolete(“Do not use. Use New Method”, true)]

public void OldMethod()

{ }

public void NewMethod()

{ }

}

Custom Attributes :

Custom attribute is a declarative information created by programmer to meet varied needs. Custom Attribute is like any other class but requires following two conditions :

  1. Custom Attribute class must declare “AttributeUsage” at class level (However, providing “AttributeUsage” attribute at class level is not must while declaring custom attribute)
  2. Custome Attribute class must derive from System.Attribute or some other attribute ultimately derived from System.Attribute.

Following is the typical example of creating Custom Attribute and its use :

public class MyAttribute : Attribute

{

public MyAttribute() {}

}

[My]

public class MyClass

{

public MyClass() {}

}

Note: it is a convention to use the word Attribute as a suffix in attribute class names. However, when we attach the attribute to a program entity, we are free not to include the Attribute suffix. The compiler first searches the attribute in System.Attribute derived classes. If no class is found, the compiler will add the word Attribute to the specified attribute name and search for it.

AttributeUsage Attribute has three properties namely,

1. AttributeTargets : Through this property, user can define the entities/targets on which custom attribute can be applied. Valid target entities settings are

· Assembly,

· Module,

· Class,

· Struct,

· Enum,

· Constructor,

· Method,

· Property,

· Field,

· Event,

· Interface,

· Parameter,

· Delegate,

Targets can be defined in different combinations for custom attributes e.g.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Constructor)]

public class MyAttribute : Attribute

{

public MyAttribute() {}

}

If user wants to allow custom attributes to be defined on all of above entities, user can use AttributeUsage(AttributeTargets.All)

2. AllowMultiple : This property defines whether this attribute can be defined on the same target multiple time or not. In following example custom attribute has been applied twice at the class level however this is valid as AllowMultiple property has been set to true. If AllowMultiple is false then following piece of code will result in compile time error.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Constructor, AllowMultiple=true)]

public class MyAttribute : Attribute

{

public MyAttribute() {}

}

[My]

[My]

public class MyClass

{

public MyClass() {}

}

3. Inherited : This property defines whether the attributes applied to targets will get inherited to derived class or not.

If AttributeUsage attribute is not applied while creating custom attribute then it will use default values. Following is the table describing these default values :

Parameter

Description

Default

AttributeTargets

What element of the class the attribute is targetting

AttributeTargets.All

IsAttributeMultiUse

Can the attribute be set multiple times.

false

IsAttributeInherited

The attribute can be inherited from derived classes.

false

Let’s consider the combination of these properties in order to understand this better.

Attribute

Targets

Allow

Multiple

Inherited

Code

Default

All

false

False

[My(“Base”)]

public class MyBase

{}

Public class MyDerived : MyBase {}

No attribute on MyDerived class

All

true

false

Still no attribute on MyDerived class as Inherited property is still false

All

false

true

[My(“Base”]

public class MyBase

{}

[My(“Derived”]

Public class MyDerived : MyBase {}

Although Inherited property is true but AllowMultiple is false, only attribute with “Derived” information will be applied to derived class

All

true

true

Attribute with both “Base” and “Derived” information will be applied to MyDerieved class

Positional vs. Named Parameters

Positional parameters are parameters of the constructor of the attribute. They are mandatory and a value must be passed every time the attribute is placed on any program entity. On the other hand Named parameters are actually optional and are not parameters of the attribute’s constructor.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Constructor, AllowMultiple=true)]

public class MyAttribute : Attribute

{

protected string name;

protected string info;

public MyAttribute(string attName)

{

name = attName;

}

public string Name

{

get { return name; }

}

public string Info

{

get { return info; }

set { info = value; }

}

}

[My(“Tau”)]

public class MyClass

{

public MyClass() {}

}

[My(“Tau”, Info = “This is additional Information”)]

public class AnotherClass

{

public AnotherClass() { }

}

In the above example, “Name” is positional parameter while “Info” is named parameter.

It is desriable to use Named parameters in attributes rather than using overloaded constructors in attribute definition.

Now, enough said about how to define attribute. Another important aspect is to how to access this declarative information. As mentioned in the beginning of the article, attribute values can be retrieved using Reflection. .Net framework provide “Attribute.GetCustomAttributes” method which returns the collection of attributes defined on given type. Overloads are available to retrieve the attributes applied to specific targets i.e. methods, constructor, etc. Following code snippet shows how to retrive the value of attribute properties.

Attribute[] attrs = System.Attribute.GetCustomAttributes(t); // reflection

foreach (Attribute attr in attrs)

{

if (attr is MyAttribute)

{

MyAttribute a = (MyAttribute)attr;

System.Console.WriteLine(“Name is {0}, Info is {1}”, a.Name, a.Info);

}

}

Few minds may have a question like the same functionality can be implemented by implementing the property in a class then why to use attribute? Following is the justification of using Attributes :

1. Attributes can be defined at different target levels i.e. methods, constructors, assembly etc. While properties can only be declared at class level.

2. Also, attribute is declarative information. So this information is assigned at the time of compilation and assigned value is not changed normally at runtime. While property value can be changed at runtime.

Advertisements
Categories: c# Tags:
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: