|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionAt the end of this article, you should be comfortable with using Custom
Attributes.
Understanding AttributesAttributes are used to add additional metadata to any element within a class (including the class itself).If you've ever customized a classes Xml serialization, you've done it using attributes. The syntax for any attribute is:
The syntax for defining a attribute is to place the following System
attribute before the class that will define your
custom: The Attribute itself can target a Class, Constructor, Field, Method, Property
or All (meaning the attribute could be applied to anything, // This custom attribute will be used to
// relate a data table name to the class definition
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ClassDataTable : Attribute
{
private string m_strDataTableName = "";
public string TableName
{
get{return m_strDataTableName;}
set{m_strDataTableName=value;}
}
public ClassDataTable(string strDataTableName)
{
m_strDataTableName = strDataTableName;
}
}
//This custom attribute will be used to relate a column name to a
//field (property only)
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class FieldDataColumn : Attribute
{
private string m_strFieldColumnName = "";
public string ColumnName
{
get{return m_strFieldColumnName;}
set{m_strFieldColumnName = value;}
}
public FieldDataColumn(string strFieldColumnName)
{
m_strFieldColumnName = strFieldColumnName;
}
Now that we have our custom attributes, let's apply them to a new class object. [ClassDataTable("People")]
public class Person
{
private string m_strFirstName = "";
private string m_strLastName = "";
private int m_intAge = 0;
[FieldDataColumn("FirstName")]
public string FirstName
{
get{return m_strFirstName;}
set{m_strFirstName = value;}
}
[FieldDataColumn("LastName")]
public string LastName
{
get{return m_strLastName;}
set{m_strLastName = value;}
}
[FieldDataColumn("Age")]
public int Age
{
get{return m_intAge;}
set{m_intAge = value;}
}
}
Reading Custom AttributesPerhaps you're not excited yet, after all, all we did was attach strings in the metadata to a class and you're not evensure how you're supposed to make any use of it (or to access it). Don't worry, it's going to get interesting. Let's make a class with some static functionality that will retrieve this metadata we've just attached. I will say in advance that the following class can and should be abstracted into something more generic (and there will be an article on it eventually) but for now, we'll keep things simple and just focus on the task at hand. If you're not comfortable or even familiar with Reflection, the good news is
you're going to be introduced. After you've public class AttributeReader
{
//Reads the ClassDataTable custom attribute from the object instance's
//metadata and returns the table name within the ClassDataTable
public static string GetBoundTable(object objTarget)
{
Type objType = objTarget.GetType();
ClassDataTable objBoundTable = (ClassDataTable) objType.GetClassAttributeByType (objTarget, typeof(ClassDataTable))[0];
return objBoundTable.TableName;
}
//Reads the FieldDataColumn custom attribute from the object instance's
//metadata and returns the column name within the FieldDataTable
public static string GetBoundColumn(object objTarget,
string strFieldName)
{
Type objType = objTarget.GetType();
PropertyInfo objField = objType.GetProperty(strFieldName);
FieldDataColumn objBoundColumn = (FieldDataColumn) objField.GetCustomAttributes (typeof(FieldDataColumn), true)[0];
return objBoundColumn.ColumnName;
}
}
All Together Now...Now that we've got the custom attributes defined, a class object with them applied and a way to read them after the fact,here's a short listing which demonstrates how this all gets used. To test all this together you will need to include the class listings above along with this to make a little console application which should give you a foundation to work with going forward. I hope this has been a helpful article and will help you in creating better data tiers in the future. Please keep in mind that the code in this article is intended to show you the principles of data binding using custom attributes and that all of the code should be optimized so that it will be practical and apply to more situations. public class CustomAttributeTesting
{
public static void Main()
{
//First we'll create a data table and fill it with a test row
DataSet objSet = CreateDataSet();
//Retreive a Person instance from the binding function
Person objPerson = GetObjectFromBinding(objSet);
//Output the values of the objPerson instance
Console.WriteLine("First Name: " + objPerson.FirstName +
"\nLast Name: " + objPerson.LastName +
"\nAge: " + objPerson.Age.ToString());
Console.WriteLine("Press Any Key To Continue");
Console.ReadKey();
}
public static DataSet CreateDataSet()
{
DataSet objSet = new DataSet();
DataTable objTable = new DataTable("People");
objTable.Columns.Add("FirstName", typeof(string));
objTable.Columns.Add("LastName", typeof(string));
objTable.Columns.Add("Age", typeof(int));
objTable.Rows.Add(new object[] {"Alex", "Robson", 27});
objSet.Tables.Add(objTable);
return objSet;
}
//This function performs the binding. It only works against the first
//row in the table.
public static Person GetObjectFromBinding(DataSet objSet)
{
Person objPerson = new Person();
string strTableName = AttributeReader.GetBoundTable(objPerson);
DataTable objTable = objSet.Tables[strTableName];
DataRow objRow = objTable.Rows[0];
string strColumnName = "";
//Although it may seem like overkill for the Person class,
//when you get into larger classes with more members this can
//be a compact way to perform the binding.
foreach (PropertyInfo objField in
typeof(Person).GetProperties())
{
strColumnName = AttributeReader.GetBoundColumn (objPerson, objField.Name);
objField.SetValue(objPerson, Convert.ChangeType (objRow[strColumnName], objField.PropertyType), null);
}
return objPerson;
}
}
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||