“Chishiki” is Japanese for “knowledge.” e-chishiki.com aims to bring software developers, information security professionals, IT executives and other IT pros a rich body of knowledge in the form of articles, interviews, tutorials and technical discussions. Our contributors are among the biggest names in the Indian IT industry and include noted authors, educators and practitioners.
C# Programming Series
C# Working with Attributes I
Yashavant Kanetkar
Serializable
This attribute is applied to a class stating that objects of this class can be serialized. When compiler encounters this attribute, it adds suitable instructions in the metadata.
There are thousands of pre-defined attributes in FCL. In addition to them .NET allows us to define our own attributes, called 'custom attributes'. In this article we would examine the process of defining and using the custom attributes and reading them using reflection.
We would create a custom attribute that can be applied to create a documentation of a class and its members. Documentation of a class includes for what the class was designed and how many methods it has. Documentation of methods includes what does they do and so on. We could write comments to know this information. However, comments remain in the source code and we may not have access to it. If we add documentation through attributes it remains in the assembly and can be accessed using reflection.
Declaring an Attribute
As everything in C# is declared in a class, an attribute is also embodied in a class. To create a custom attribute we have to derive a class from the System.Attribute class. We have named our derived class as DocumentAttribute. The class DocumentAttribute has three data members as shown below.
class DocumentAttribute : System.Attribute
{
string info ;
int cnt ;
}
The string variable info keeps description of the entity and the integer variable cnt keeps count of the methods. We can declare attributes either with parameters or without parameters. The parameters can be positional parameters or named parameters. The positional parameters are initialized in constructor, whereas, named parameters are initialized by defining a property. Another difference between the two is that positional parameters must be passed in the same sequence as given in the constructor. The named parameters are optional and can be passed in any sequence. We have declared the Document attribute to take two parameters. We want that one of them viz. info should be positional parameter and cnt should be named parameter. This is because cnt would be used only if attribute is applied to class. For class members we can drop it. So, we must define a constructor and a property as shown below.
public DocumentAttribute ( string i )
{
info = i ;
}
public int Count
{
get
{
return cnt ;
}
set
{
cnt = value ;
}
}
As we know, custom attributes are written in metadata and can be read through reflection. Generally speaking reading an attribute means reading values of data members of the attribute class. If we try to read the Document attribute it won't be able to access the info data member as it is declared private. So, in order to expose it through metadata, we would write a read-only property. Here it is.
public string Info
{
get
{
return info ;
}
}We must also mention the attribute targets. This can be done by using nothing else than an attribute called AttributeUsage. The AttributeUsage attribute targets classes. So, it has to be declared just above the DocumentAttribute class as shown below.
[ AttributeUsage ( AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Constructor |
AttributeTargets.Field, AllowMultiple = false ) ]
class DocumentAttribute : System.Attribute
{
}
The AttributeUsage attribute takes two parameters. Using the first parameter we can specify attribute targets. By setting the second parameter to true we can specify that one member can have multiple Document attributes. When attribute targets are assembly or module, the attributes should be placed immediately after all using statements and before any code.



