SIGN UP MEMBER LOGIN:    
ARTICLE

Attributes in C#

Posted by Suchit Khanna Articles | C# Language June 08, 2011
In this series we will see the usage of “Attribute” with the help of some examples and creation of our own custom attributes to be used in a sample use case.
Reader Level:
Download Files:
 


Use Case:

We will be creating a custom Attribute class that will take "IList" based collections and convert them into a "DataTable".

Further we will take the converted DataTable and bind it to a DataGridView with the help of a sample application to elaborate our Custom Attribute class we made.

Using your Visual Studio create a "Class Library" based project:

Attribute.gif

Next in the project create a new class with the name: TableColumns next add the following code to your class:

/// <summary>
///
Repsent a custom attribute which specifes the meta information about properties
/// of a given type, whether to be shown in DataGridView or not.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class TableColumns : Attribute
{

}

*Note
: Whenever we make a CustomAttribute for our use, it has to derive from the Attribute class available from the framework.

In the above code snippet we have specified some rules for our custom attribute class that resticts the usage of our custom attribute: Let us see in detail what each will do:

AttributeTargets.Property:

This tells the compiler that our custom attribute will be applicable only to the properties (i.e. getters and setters can only be tagged with our attribute).

AllowMultiple = false:

This tells the compiler that not more than once can we apply a custom attribute to the same element.

Inherited = true:

This line tells the compiler whether the classes deriving from the Base class using this Atrribute should inherit these attribute tags in the derived class or not (we will see this in more detail using a code snippet).

We will see further in our sample application how these fileds effect the working of our custom attribute.

Now let us move ahead and complete our custom attribute class. Declare two private variables for the class:

private MappingType m_columnMapping;
private string      m_columnName = null;

And make an overloaded constructor along with a default constructor:

  /// <summary>
        /// Default Constructor.
        /// </summary>
        public TableColumns() { }
        /// <summary>
        /// Overloaded Constructor.
        /// </summary>
        /// <param name="columnName">The name of the column.</param>
        /// <param name="mappingType">The type of mapping.</param>
        public TableColumns(string columnName, MappingType mappingType)
        {
            m_columnMapping = mappingType;
            m_columnName = columnName;
        }

We are initializing the private variables declared in the beginning here in the overloaded constructors.

  /// <summary>
        /// Gets or Sets the name of the column.
        /// </summary>
        public string ColumnName
        {
            get { return m_columnName; }
            set { m_columnName = value; }
        }

        /// <summary>
        /// Gets or Sets the mapping type associated with the column.
        /// </summary>
        public MappingType ColumnMappingType
        {
            get { return m_columnMapping; }
            set { m_columnMapping = value; }
        }

Ok, with the above code we are finished creating our Custom Attribute Class that will be used on the Model Classes to tag with.

Now next we need an extension method to read the data from objects which are tagged with our Custom Attribute classes. For that add a new class in the project named:

ListExtensions.cs

public static class ListExtensions
{

}

Next tag the class with a static attribute (as the extension methods can live in static classes only); then add the following method:

/// <summary>
///
Extension Method to convert the IList type source to a DataTable
/// </summary>
///
<param name="_source">Any type that implements IList interfaces.</param>
///
<returns></returns>
public static DataTable ToDataTable(this IList _source)
{

}

We have made an extension method ToDataTable that will be available for ICollection implemented classes and can create a DataTable out of it.

Next we need to determine the properties that are tagged with our CustomAttribute "TableColumns", and all these properties need to be converted to corresponding DataColumns of the DataTable; for that we implement the following:

if (_source != null && _source.Count > 0)
{
DataTable dataTable = new DataTable();

      Type elementType = _source[0].GetType();
      dataTable.TableName = elementType.Name;

      PropertyInfo[] propertyInfo = _source[0].GetType().GetProperties();
 
      for (int i = 0; i < propertyInfo.Length; i++)
      {
Attribute[] attInfo = propertyInfo[i].GetCustomAttributes(typeof(TableColumns), false) as Attribute[];

            if (attInfo != null && attInfo.Length > 0)
            {
                  for (int j = 0; j < attInfo.Length; j++)
                  {
 
                        TableColumns attribute = attInfo[j] as TableColumns;

                        DataColumn column = new DataColumn();
 
if (attribute.ColumnName == string.Empty ||     attribute.ColumnName == null)
                        {
                              column.ColumnName = propertyInfo[i].Name;
                        }
                        else
                        {
                              column.ColumnName = attribute.ColumnName;
                        }
 
if (attribute.ColumnMappingType ==  MappingType.Hidden)
column.ColumnMapping = attribute.ColumnMappingType;
 
column.DataType = propertyInfo[i].PropertyType;
 
                                dataTable.Columns.Add(column);
                            }
                        }
                    }

Ok let us dissect what we are doing here:

Type elementType = _source[0].GetType();
dataTable.TableName = elementType.Name;


Here we are getting the type of the elements that our IList stores and based on that we give a default name to our DataTable, next using reflection we are getting the properties available for that type:

PropertyInfo[] propertyInfo = _source[0].GetType().GetProperties();

In the subsequent code we loop through all the properties and find all the properties tagged with our custom attribute:

Attribute[] attInfo = propertyInfo[i].GetCustomAttributes(typeof(TableColumns), false) as Attribute[];

From the above piece of code we get the attribute information and based on that we create as many DataColumns. Next follows:

if (attribute.ColumnName == string.Empty || attribute.ColumnName == null)
{
column.ColumnName = propertyInfo[i].Name;
}
else
{
column.ColumnName = attribute.ColumnName;
}

In case there is no explicit ColumnName specified in the Attribute tagged over the property we name the DataColumn with the name of the Property.

if (attribute.ColumnMappingType == MappingType.Hidden)
column.ColumnMapping = attribute.ColumnMappingType;


Now similarly if MappingType specified is Hidden, the same is specified in the DataColumn to hide that column in the while displaying on screen. And by default the data type of the DataColumn is that of Property.

column.DataType = propertyInfo[i].PropertyType;

This concludes our DataTable schema creation; next we need to extract data from the list and create rows in the DataTable which will be eventually returned, for that:

for (int i = 0; i < _source.Count; i++)
{
int j = 0;
      object[] fieldValues = new object[dataTable.Columns.Count];
      for (; j < propertyInfo.Length; j++)
      {
            MemberInfo mi = elementType.GetMember(propertyInfo[j].Name)[0];
            if (mi.MemberType == MemberTypes.Property)
            {
                  PropertyInfo pi = mi as PropertyInfo;
                  fieldValues[j] = pi.GetValue(_source[i], null);
            }
       }
       dataTable.Rows.Add(fieldValues);
}


We again make use of reflection to get the Members of the object and figure out whether they are properties and eventually make use of GetValue() function to get their values and fill up the rows.

This concludes our first part where we made a Custom Attribute and implemented an Extension method that will enable us to use that Custom Attribute. In the next series we will see how we can leverage the Custom Attribute we made in an application.
 

Login to add your contents and source code to this article
share this article :
post comment
 

Thanks :)

Posted by Suchit Khanna Jun 08, 2011

Nice Imformative article...suchit

Posted by Shirsendu Nandi Jun 08, 2011
Become a Sponsor
PREMIUM SPONSORS
  • Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
    ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications. Visit DynamicPDF here
Nevron Gauge for SharePoint
Become a Sponsor