Tools Used
Visual C# .NET
What are Attributes?
Here is a quote about what an attribute is all about:
"Attributes provide a powerful method of associating declarative information with C# code (types, methods, properties, and so forth). Once associated with a program entity, the attribute can be queried at run time and used in any number of ways." - MSDN
Attributes are classes that allow you to add additional information to elements of your class structure.
The information from the attribute can later be obtained by using Reflection. See the article on reflection on this site. In this article, we will show you how to add stereotypes to your method. A stereotype is a way to describe a specific category for a design element and is a term that comes from UML. Our stereotype attribute provides two strings to describe our methods, a stereotype string and a description string.
Below is the code for declaring our custom attribute, stereotype,
using System;
using System.Reflection;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Constructor)]
public class Stereotype: System.Attribute {
public string TheStereotypeName = "General";
public string TheDescription = "Method Info";
public Stereotype() {}
public Stereotype(string aStereotype, string aDescription) {
TheStereotypeName = aStereotype;
Description = aDescription;
}
}
Every class requires two things to make it an attribute.
- An AttributeUsage Attribute to declare the class as an attribute.
- Derive from System.Attribute or some other attribute ultimately derived from System.Attribute.
Below is the attribute usage from our example allowing our attribute to be associated with a class or a method or a constructor of a class,
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Constructor)]
This element before the class takes 3 possible parameters.
Parameter |
Description |
Default |
Example |
AttributeTargets |
What element of the class the attribute is targetting |
AttributeTargets.All |
the sample attribute targets classes constructors, and methods (see above) |
IsAttributeMultiUse |
Can the attribute be set multiple times. |
false |
[Conditional("A"),Conditional("B")] |
IsAttributeInherited |
The attribute can be inherited from derived classes. |
false |
|
To use our attribute, we simply place it above a method, and call the attribute's constructor. Below is an example of the Stereotype Attribute being used in a class called Customer with methods GetName and SetName. For simplicity, only the methods are displayed below,
// method 1 of our Customer class
[Stereotype("Accessor", "Retrieve the name of the customer")]
public string GetName() {
return Name;
}
// Method 2 of our customer class
[Stereotype("Modifier", "Set the name of the customer")]
public void SetName(string aName) {
Name = aName;
}
Now we'll add a method to our stereotype attribute class that will allow us to retrieve the attribute information from the customer class and write it to the console. The method uses reflection and calls GetCustomAttributes on each item in our methodinfo collection to get a hold of the stereotype attributes of our class,
public static void WriteEachMethodInClass(Type t) // method of the Stereotype class
{
System.Console.WriteLine("Methods for Class {0}", t.Name); // write class name to console
MethodInfo[] TheMethods = t.GetMethods(); // Get all the methods from the class using reflection
for (int i = 0; i < TheMethods.GetLength(0); i++) // cycle through each method and see if it has an attribute
{
MethodInfo mi = TheMethods[i];
object[] attrs = mi.GetCustomAttributes(); // Get collection of custom attributes from the method
foreach(Attribute attr in attrs) // get each attribute using foreach
{
if (attr is Stereotype) // is the attribute a Stereotype Attribute?
{
Stereotype theStereotype = (Stereotype) attr; // it is, write the Stereotype and the Description to the console
System.Console.WriteLine("{0} - {1}, {2}", mi.Name, theStereotype.TheStereotype, theStereotype.Description);
}
}
}
ConstructorInfo[] TheConstructors = t.GetConstructors(); // do the same for the constructors of our class
for (int i = 0; i < TheConstructors.GetLength(0); i++) {
ConstructorInfo mi = TheConstructors[i];
object[] attrs = mi.GetCustomAttributes();
foreach(Attribute attr in attrs) {
if (attr is Stereotype) {
Stereotype theStereotype = (Stereotype) attr;
System.Console.WriteLine("{0} - {1},{2}", mi.Name, theStereotype.TheStereotype, theStereotype.Description);
}
}
}
}
Here is an example of how we call our WriteEachMethodInClass to write out the stereotype attributes,
public static int Main(string[] args) {
Stereotype.WriteEachMethodInClass(typeof(Account)); // Write the stereotype information of Account to the console.
Stereotype.WriteEachMethodInClass(typeof(Customer)); // Write the stereotype information of Customer to the console.
System.Console.WriteLine("Hit ENTER to continue...");
System.Console.Read();
return 0;
}
Attributes can be used from everything to detailed code documentation, to version control. Look for future articles on this subject coming to C-Sharp Corner.