Attributes are widely used in .Net libraries such as XML serialization. The syntax of attributes is very confusing until you realize that attributes are actually classes. This article provides a quick guide to understanding attribute syntax, how to read it, and how to look up an attribute documentation to be able to spcify them in your programming practice.
This article is not a thorough reference on attributes but a quick stab at the main features of attributes so that you can gain an understanding of attributes and start using them after the first read.
Attributes are used all over the place in .Net. Let us consider an XML serialization example where attributes take an important and necessary role. In this example we will be designing a c# class and stream it as XML. The c# class definition follow:
Public class MyClass
{
public string myField = "abc";
}
The above class can be streamed as XML as follows
MyClass myObject = new MyClass;
XmlSerializer xs = new XmlSerializer(typeof(myObject));
StringWriter sw = new StringWriter();
Xs.serialze(sw,myObject);
This will produce an XML as follows
<MyClass>
<myField>abc</myField>
</MyClass>
Let us now introduce attributes so that the generated XML can be tailored
[XmlRoot("MyXmlClass")]
Public class MyClass
{
[XmlElement(ElementName="myXmlField")]
public string myField = "abc";
}
This will produce an XML as follows
<MyXmlClass>
<myXmlField>abc</myXmlField>
</MyXmlClass>
There are lot more attributes in XML serialization to control the serialization process. You can see these attributes in the references section of this article. But for now these two attributes are sufficient for our discussion.
When I have encountered these attributes first my first problem was figuring out how to read this attribute specification. What is the meaning of "[XmlRoot("somename")]"? I could guess that they are trying to set the name of the root node of the XML. But the syntax is unclear because in one case they are specifying a string directly inside quotes, in another case they are using some sort of a key to specify the string against.
Some times they use commas to separate multiple attributes, and sometimes they stack them. Sometimes there are repeated attributes and sometimes not. Sometimes they seem to be applied to fields and sometimes to classes. It seemed to be a very inconsistent set of rules.
But it turns out there is a mehtod to this madness afterall. The key to understanding to attributes lies in the fact that they represent .Net classes (first class citizens of the .net world). Let us investigate this aspect of attributes for a second.
When you specify an attribute you are actually allowing the .net to instantiate a class represented by that attribute. Because of this the specification of an attribute resembles the syntax of a class constructor where all the arguments to the constructor are static and specified at compile time.
Because an attribute is a class, an attribute's name is a classname. A classname includes a namespace and so does an attributes name. So what class does "XmlRoot" represent? This name is a short cut for "System.xml.serialiation.XmlRootAttribute". I will show you later how this long name shrinked to a just "XmlRoot".
Because attributes are classes you need to specify the "using" clause to import the namespace they are part of. So in the above case by importing the "System.xml.Serialization" namespace you can shorten the name to "XmlRootAttribute".
An exception to the above construction rule is that the attribute specification allows you not only to construct a class but also set its public properties. This means that if the class has some public properties, the specification needs to accommodate a way to set these properties as well. The construction syntax is extended to manage this need. The public properties are named and specified following the regular arguments usinga key/value pair syntax
Documentation of an attribute (because it��s a class) is available just like the documentation of any other c# class. You look up the arguments of its constructor and you look up the public properties of the attribute class. An attribute documentation in addition will also specify what programming constructs for which this attribute is applicable.
Public properties of an attribute class are set using key/value pair combinations followed by the mandatory arguments of its constructor.
While encountering attributes the thing that throws you off the most is the varieties of syntax that can be used to specify an attribute. Let me address the common usage patterns of specifying an attribute
[namespace.attributeNameAttribute](arg1,arg2,param1=value,param2=value);
[attributeNameAttribute](arg1,arg2,param1=value,param2=value);
[attributeName](arg1,arg2,param1=value,param2=value);
The first line identifies a fully qualified class name of an attribute followed by the constructor arguments, followed by the public properties. The second line omits the namespace from the fully qualified name. The third line omits the "Attribute" suffix from the class name. This is purely a convenience offered by the programming facilities. Let us see some examples demonstrating these variations.
1. [System.Xml.Serialization.XmlRootAttribute(ElementName="LOAD_TENDER_TRIP", Namespace="", IsNullable=false)]
2. [System.Xml.Serialization.XmlRootAttribute("LOAD_TENDER_TRIP", Namespace="", IsNullable=false)]
3. [XmlRootAttribute(ElementName="LOAD_TENDER_TRIP", Namespace="", IsNullable=false)]
4. [XmlRoot(ElementName="LOAD_TENDER_TRIP", Namespace="", IsNullable=false)]
It is time to summarize the various rules governing the attributes
[attribute1()]
[attribute2()]
[attribute1(), attribute2()]
[attribute1]