Extending DataRow with a generic Fill method ( map DataRow directly to user typed object )

23 ביולי 2009

2 תגובות


Background:


Every developer creates a lot of classes based on database tables, the data binding is a routing i wanted to save.


 so,


First we had to create new attribute to bind the databse column to our field/property, then we had to creare the extention. 


here is the source code of my class:


Source:





/// <summary>
/// Uses to bind field or property to a specific database column
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)]
public class ColumnAttribute : Attribute
{
public string ColumnName;
public object DefaultValue;
/// <summary>
/// Initializes a new instance of the <see cref="ColumnAttribute"/> class.
/// </summary>
/// <param name="ColumnName">Name of the column.</param>
public ColumnAttribute(string ColumnName)
{
   this.ColumnName = ColumnName;
}
/// <summary>
/// Initializes a new instance of the <see cref="ColumnAttribute"/> class.
/// </summary>
/// <param name="ColumnName">Name of the column.</param>
/// <param name="DefaultValue">The default value.</param>
public ColumnAttribute(string ColumnName, object DefaultValue)
  :
this(ColumnName)
 {
   this.DefaultValue = DefaultValue;
 }
}

/// <summary>
/// Extending DataRow object with the generic Fill method
/// </summary>
public static class DataRowExtention
{
/// <summary>
/// Fills the T object this the row data. (the T object must have "ColumnAttribute" attribute on it's fields or properties)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj">The object to fill</param>
public static void Fill<T>(this DataRow oRow, T obj)
{
 if ( oRow == null )
   throw new ArgumentNullException("DataRow cannot be null");
 if ( obj == null )
   throw new ArgumentNullException("Object cannot be null"); //Set Fields

 FieldInfo[] oFields = typeof(T).GetFields();
 for (int i = 0; i < oFields.Length; i++)
 {
   FieldInfo oField = oFields[i];
   Attribute[] attributes = Attribute.GetCustomAttributes(oField, typeof(ColumnAttribute), false);
   foreach (Attribute attribute in attributes)
   {
     ColumnAttribute oColumnAttributeName = (ColumnAttribute)attribute;
     if (oRow[oColumnAttributeName.ColumnName] != DBNull.Value)
        oField.SetValue(obj, oRow[oColumnAttributeName.ColumnName]);
     else
        oField.SetValue(obj, oColumnAttributeName.DefaultValue);
     break;
   }
 }

 //Set Properties
 PropertyInfo[] oProperties = typeof(T).GetProperties();
 for (int i = 0; i < oProperties.Length; i++)
 {
   PropertyInfo oProperty = oProperties[i];
   if (!oProperty.CanWrite)
     continue;
   Attribute[] attributes = Attribute.GetCustomAttributes(oProperty, typeof(ColumnAttribute), false);
   foreach (Attribute attribute in attributes)
   {
     ColumnAttribute oColumnAttributeName = (ColumnAttribute)attribute;
     if (oRow[oColumnAttributeName.ColumnName] != System.DBNull.Value)
        oProperty.SetValue(obj, oRow[oColumnAttributeName.ColumnName], null);
     else
        oProperty.SetValue(obj, oColumnAttributeName.DefaultValue, null);
     break;
  }
 }
}
}




Usage:





public class MemberDO
{
   [
ColumnAttribute("Id")] // Binds column "Id".
   public int MemberID;

   [ColumnAttribute("Name", "Temp")] // Binds column "Name" with the default value "Temp".
   public string Fullname;
}




Example:





//Create dummy data
DataTable dt = new DataTable();
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Name", typeof(string));

 

// Set both fields.
DataRow dr = dt.NewRow();
dr["Id"] = 1234;
dr["Name"] = "Evyatar Shalom"; MemberDO member = new MemberDO();
dr.Fill<MemberDO>(member);

// Set only one field.
DataRow dr2 = dt.NewRow();
dr2["Id"] = 1234;


MemberDO member2 = new MemberDO();
dr2.Fill<MemberDO>(member2); // In this case member2.Fullname will be set to default "Temp".


 


now.. stop reading blogs and have some fun 🙂


 

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *

2 תגובות

  1. evyevy23 ביולי 2009 ב 9:52

    חח אז אני לא המצאתי את הגלגל 🙂

    נחמד.. הרעיון דומה הביצוע שונה..

    אה.. ולידע כללי, עשיתי בדיקות ביצועים,
    אין ספק Reflection יותר איתי.. אבל המטרה היא לכל המחלקות שלא נטענות מליון פעם. ואז זה לא מורגש..

    הגב