Wednesday, June 22, 2011

C# - Attributes


Attributes

An attribute is an object that represents data you want to associate with an element in your program. The element to which you attach an attribute is referred to as the target of that attribute. For example, the attribute:
[NoIDispatch]
is associated with a class or an interface to indicate that the target class should derive from IUnknown rather than IDispatch, when exporting to COM. 

Attributes come in two flavors: intrinsic and customIntrinsic attributes are supplied as part of the Common Language Runtime (CLR), and they are integrated into .NET. Custom attributes are attributes you create for your own purposes.
Most programmers will use only intrinsic attributes, though custom attributes can be a powerful tool when combined with reflection.

Creating the custom attribute class
We are going to create a Customer data class as an example of something you would do often in a data application. We are going to create a custom attribute to mark the data fields that are saved in the database so as to differenciate them from other fields in the class.
First we will create the custom attribute class called DataFieldAttribute. When you create a custom attribute you must inherit from the Attribute class. Here is the code.
using System;

public class DataFieldAttribute : Attribute
{
}

Applying the custom attribute

Now we will create the Customer data class that the DataFieldAttribute will be applied to. We are just going to use a very simple example of a Customer class that only has the first name, last name and a method for getting the full name. Our goal is to apply the DataField attribute to the first name and last name fields because they are the only ones that must be saved in the database. Here is the Customer class code.
using System;

class Customer
{
   public string FirstName;
   public string LastName;

   public string FullName
   {
      get { return FirstName + " " + LastName; }
   }
}

The interesting thing about attributes is that when you create the attribute class you have to add the word Attribute to the end of the name of the class but when you apply the attribute to something then you have to use it without Attribute added to the name. Here is the same code from above with the DataField attribute applied to the data fields.
using System;

class Customer
{
   [DataField]
   public string FirstName;
   [DataField]
   public string LastName;

   public string FullName
   {
      get { return FirstName + " " + LastName; }
   }
}

Using the custom attribute

Now we can finally get round to using the attribute. To do this we will have to instantiate a Customer object and set its values. We are not going to include all the database stuff so you will just have to imagine that it is happening. After that we will loop through all the data fields and get their values and display them to see if the DataField attribute works properly. Here is the code.
// Instantiate Customer and initialize it
Customer cust = new Customer();
cust.FirstName = "John";
cust.LastName = "Smith";

// Get all members of the Customer class and loop through them
System.Reflection.MemberInfo[] CustomerMembers = cust.GetType().GetMembers();
foreach (System.Reflection.MemberInfo mi in CustomerMembers)
{
   // Get the custom attributes on the member for DataFieldAttribute only
   object[] attributes = mi.GetCustomAttributes(typeof(DataFieldAttribute), true);
   // If this member has at lease one DataFieldAttribute then display it to the user
   if (attributes.Length > 0)
   {
      System.Windows.Forms.MessageBox.Show(mi.Name);
   }
}

This is a very simple example but from it you should be able to figure out how to adapt it to suit the situations that you come across.

Parameters

You can give your attributes parameters by creating a constructor for your attribute class. Here is an example of adding a constructor to the DataFieldAttribute class and then an example of using the parameter in the Customer class.
using System;

public class DataFieldAttribute : Attribute
{
   public DataFieldAttribute(string DatabaseFieldName)
   {
   }

}


using System;

class Customer
{
   [DataField("FName")]
   public string FirstName;
   [DataField("LName")]
   public string LastName;

   public string FullName
   {
      get { return FirstName + " " + LastName; }
   }
}

Here is the code based on an example higher up which you can use to get the value of the parameter.
// Instantiate Customer and initialize it
Customer cust = new Customer();
cust.FirstName = "John";
cust.LastName = "Smith";

// Get all members of the Customer class and loop through them
System.Reflection.MemberInfo[] CustomerMembers = cust.GetType().GetMembers();
foreach (System.Reflection.MemberInfo mi in CustomerMembers)
{
   // Get the custom attributes on the member for DataFieldAttribute only
   object[] attributes = mi.GetCustomAttributes(typeof(DataFieldAttribute), true);
   // If this member has at lease one DataFieldAttribute then display it to the user
   if (attributes.Length > 0)
   {
      DataFieldAttribute dfa = (DataFieldAttribute)attributes[0];
      System.Windows.Forms.MessageBox.Show(dfa.DatabaseFieldName);

   }
}



You can also define where your custom attributes can be applied like, Class Fields, Properties, Function etc. by using AttributeUsage keyword
[AttributeUsage(AttributeTargets.Class |

    AttributeTargets.Constructor |
    AttributeTargets.Field |
    AttributeTargets.Method |
    AttributeTargets.Property,
    AllowMultiple = true)]
Restricting usage
You can restrict what your attribute can be applied to by using the AttributeUsage attribute on your attribute. Here is an example of how to restrict the attribute to being used with only fields.
using System; [AttributeUsage(AttributeTargets.Field)] public class DataFieldAttribute : Attribute { } using System; class Customer {    [DataField] // Allowed    public string FirstName;    [DataField] // Allowed    public string LastName;    [DataField] // NOT Allowed    public string FullName    {       get { return FirstName + " " + LastName; }    } }



No comments:

Post a Comment