用反射實現將數據自動填充到對象中,學習orm的半個功能

    最近整理以前的資料,想起來了這個小東西,以前感覺反射效率應該不行,後來翻看了nhibernate的源代碼徹底改變了我的觀點,隨後自己動手寫了這個小東西玩玩,大牛就不用看了,對反射有意思的可以瞧瞧偷笑

    基本原理說明,我將業務類用自定義屬性[CustAttribute]進行標註,然後用ado.net 獲取數據集,將數據集中列名與對應業務類屬性名稱相同的進行填充操作,思路簡單明瞭。

    自定義CustAttribute類:


  /// <summary>
    /// 自定義屬性類,用於識別要映射的屬性
    /// </summary>
    //[AttributeUsage(Inherited = true,AllowMultiple =true)]
	public class CustAttribute:Attribute
	{


	}
     結果集映射類:

    

/// <summary>
    /// 將DataTable映射到class
    /// </summary>
    /// <typeparam name="T"></typeparam>
	public class DataRowClassMap<T> where T: class 
	{
        /// <summary>
        /// 將DataRow中的數據映射到item中
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public static T GetData(DataRow dr, T item)
        {
            if (item ==null||dr == null || dr.Table.Columns.Count == 0)
                return null;
            //獲取類的公共屬性
            List<PropertyInfo> SelfPropertyList = GetSelfProperties(typeof(T));
            //循環獲得各個屬性
            foreach (PropertyInfo info in SelfPropertyList)
            {
                //判斷當前DataRow中是否含有當前屬性
                if (dr.Table.Columns.Contains(info.Name) == false)
                {
                    LibraryException.WriteErrorLoc(string.Format("沒有找到類{0}的{1}屬性", typeof(T).ToString(),info.Name));
                    return null;
                }
                if (dr[info.Name] == DBNull.Value)
                { 
                    //如果是可空類型則直接賦值爲null
                    if (info.GetValue(item, null) == null)
                    {
                        continue;
                    }
                    //不是空類型也直接返回
                    continue;
                }
                //根據屬性類型獲取對應的轉換值
                object value = GetTypeValue(info, dr[info.Name]);
                if (value == null)
                {
                    LibraryException.WriteErrorLoc(string.Format("數據轉換失敗!類{0}的{1}屬性嘗試將值{3}轉換失敗", typeof(T).ToString(), info.Name,dr[info.Name]));
                    return null;
                }
                info.SetValue(item, value, null);
            }
            return item;
        }
        /// <summary>
        /// 獲得當前類中自定義屬性,不包含繼承的
        /// </summary>
        /// <param name="type"></param>
        private static List<PropertyInfo> GetSelfProperties(Type type)
        {
            List<PropertyInfo> SelfPropertyList = null;
            try
            {
                  //獲取對象的共有屬性,並且是標誌了自定義特性的屬性。
                  SelfPropertyList = type.GetProperties(BindingFlags.Public
                  | BindingFlags.Instance | BindingFlags.DeclaredOnly)
                  .ToList().FindAll(x => x.MemberType == MemberTypes.Property&&x.GetCustomAttributes(typeof(CustAttribute),false).Count()>0);
            }
            catch (Exception ex)
            {
                LibraryException.WriteErrorLoc(ex.Message);
            }
            return SelfPropertyList;
        }
        /// <summary>
        /// 根據類型獲取對應的類型值
        /// </summary>
        /// <param name="info"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        private static object GetTypeValue(PropertyInfo info, object p)
        {
            try
            {
                Type type = info.PropertyType;
                //判斷是否是Nullable<>類型
                if (type.IsGenericType == true && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    //獲取基類型
                    type = type.GetGenericArguments()[0];
                }
                //如果等於string類型
                if (type.Equals(typeof(string)))
                    return p;
                if (type.Equals(typeof(Guid)))
                    return new Guid(p.ToString());
                if (type.Equals(typeof(DateTime)))
                    return DateTime.Parse(p.ToString());
                MethodInfo methord = type.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, new Type[] {typeof(string)},null);
                if (methord == null)
                {
                    LibraryException.WriteErrorLoc(string.Format("數據轉換失敗!類{0}的{1}屬性沒有Parse(string)方法", info.DeclaringType.Name, info.Name));
                    return null;
                }
                var value = methord.Invoke(null, new object[] { p.ToString() });
                return value;
            }
            catch (Exception ex)
            {
                LibraryException.WriteErrorLoc(string.Format("數據轉換失敗!類{0}的{1}屬性嘗試將值{3}轉換失敗,失敗原因{4}", info.DeclaringType.Name, info.Name,p.ToString(),ex.Message));
                return null;
            }
        }
	}
               使用示例:

               有如下Order業務類定義

               

public  class SaleOrder
    {
        #region 屬性
        [<span style="font-family: Arial, Helvetica, sans-serif;">CustAttribute</span><span style="font-family: Arial, Helvetica, sans-serif;">]</span>
        public Guid ID { get; set; }
        /// <summary>
        /// 主鍵ID
        /// </summary>
<pre name="code" class="csharp">        [<span style="font-family: Arial, Helvetica, sans-serif;">CustAttribute</span><span style="font-family: Arial, Helvetica, sans-serif;">]</span>

        public string OrderName {get;set;}
        <pre name="code" class="csharp">        [<span style="font-family: Arial, Helvetica, sans-serif;">CustAttribute</span><span style="font-family: Arial, Helvetica, sans-serif;">]</span>
<span style="font-family: Arial, Helvetica, sans-serif;">                public decimal Amount {get;set;}</span>
<span style="font-family: Arial, Helvetica, sans-serif;">              ........................</span>

        

           需求是根據ID獲取單個SaleOrder數據

/// <summary>
        ///根據ID獲取SaleOrder對象
        /// </summary>
        /// <param name="ID"></param>
        public static  SaleOrder GetDataByID(Guid ID)
        {
            try
            {
                string sqlstr = string.Format("select top 1 * from Inv_SaleOrder where  ID='{0} '",ID.ToString());
                DataTable table = DataAccess.GetDataTable(sqlstr);
                if (table == null || table.Rows.Count == 0)
                    return null;
                SaleOrder order = new SaleOrder(); 
                DataRow dr = table.Rows[0]; //獲得一行數據
                DataRowClassMap<SaleOrder>.GetData(dr, order);//填充對象
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

   如果沒有DataRowClassMap 進行填充數據,那我就得用如下的方法敲代碼,一個類還行,要是多了手酸眼花
<pre name="code" class="csharp"> #region 老代碼
        //private void GateData(DataRow dr)
        //{
        //    this.TaxStkAmount = decimal.Parse(dr["TaxStkAmount"].ToString().Trim());
        //    this.LocTaxStkAmount = decimal.Parse(dr["LocTaxStkAmount"].ToString().Trim());
        //    this.StkAmountTax = decimal.Parse(dr["StkAmountTax"].ToString().Trim());
        //    this.LocStkAmountTax = decimal.Parse(dr["LocStkAmountTax"].ToString().Trim());
        //    this.TaxSrvAmount = decimal.Parse(dr["TaxSrvAmount"].ToString().Trim());
        //    this.LocTaxSrvAmount = decimal.Parse(dr["LocTaxSrvAmount"].ToString().Trim());
        //    this.LocSrvAmountTax = decimal.Parse(dr["LocSrvAmountTax"].ToString().Trim());
        //    this.TaxAmount = decimal.Parse(dr["TaxAmount"].ToString().Trim());
        //    this.TaxAllowance = decimal.Parse(dr["TaxAllowance"].ToString().Trim());
        //    this.LocTaxAllowance = decimal.Parse(dr["LocTaxAllowance"].ToString().Trim());
        //    this.AmountTax = decimal.Parse(dr["AmountTax"].ToString().Trim());
        //    this.LocAmountTax = decimal.Parse(dr["LocAmountTax"].ToString().Trim());
        //    this.LocTaxTrnAmount = decimal.Parse(dr["LocTaxTrnAmount"].ToString().Trim());
        //    this.TaxTrnAmount = decimal.Parse(dr["TaxTrnAmount"].ToString().Trim());
        //    this.Payment_ID = int.Parse(dr["Payment_ID"].ToString().Trim());
        //    this.MnyNo = dr["MnyNo"].ToString().Trim();
        //    this.ExRate = decimal.Parse(dr["ExRate"].ToString().Trim());
        //    this.DocNumber = dr["DocNumber"].ToString().Trim();
        //    this.TrnDate = DateTime.Parse(dr["TrnDate"].ToString().Trim());
        //    this.AcntPeriod = dr["AcntPeriod"].ToString().Trim();
        //    this.PostDate = DateTime.Parse(dr["PostDate"].ToString().Trim());
        //    this.DocFlag = int.Parse(dr["DocFlag"].ToString().Trim());
        //    this.SendDate = DateTime.Parse(dr["SendDate"].ToString().Trim());
        //    this.UpdatedBy = dr["UpdatedBy"] == DBNull.Value ? new Nullable<Guid>() : new Guid(dr["UpdatedBy"].ToString().Trim());
        //    this.UpdateTime = dr["UpdateTime"] == DBNull.Value ? new Nullable<DateTime>() : DateTime.Parse(dr["UpdateTime"].ToString().Trim());
        //    this.Description = dr["Description"].ToString().Trim();
        //    this.ProjectID = new Guid(dr["ProjectID"].ToString().Trim());
        //    this.SaleManID = new Guid(dr["SaleManID"].ToString().Trim());
        //    this.CustID = new Guid(dr["CustID"].ToString().Trim());
        //    this.DeptID = new Guid(dr["DeptID"].ToString().Trim());
        //    this.DocTypeID = new Guid(dr["DocTypeID"].ToString().Trim());
        //    this.Name = dr["Name"].ToString().Trim();
        //    this.Title = dr["Title"].ToString().Trim();
        //    this.Tel = dr["Tel"].ToString().Trim();
        //    this.mtel = dr["mtel"].ToString().Trim();
        //    this.Fax = dr["Fax"].ToString().Trim();
        //    this.Addres = dr["Addres"].ToString().Trim();
        //    this.email = dr["email"].ToString().Trim();
        //    this.PostCode = dr["PostCode"].ToString().Trim();
        //    this.IsClose = bool.Parse(dr["IsClose"].ToString().Trim());
        //    this.TaxKind = int.Parse(dr["TaxKind"].ToString().Trim());
        //    this.Shop_ID = int.Parse(dr["Shop_ID"].ToString().Trim());
        //    this.ToWareHouse_ID = int.Parse(dr["ToWareHouse_ID"].ToString().Trim());
        //}
        #endregion



經測試速度還可以的,如果你說有用EF,Nhibernate 等主流的ORM,還用這個幹啥,當我大多情況下只需要讀數據,並且業務類比較少量,邏輯簡單的情況下 幹嘛還用搞nh,EF, 殺雞焉用牛刀呢,對吧,最主要是研究學習orm的功能,讀已經實現了,寫也就是個逆過程,以後有空有心情了留待實現吧,盡請期待<img alt="偷笑" src="http://static.blog.csdn.net/xheditor/xheditor_emot/default/titter.gif" />
</pre><pre name="code" class="csharp"><p style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; line-height: 26px;"><strong><span style="color: rgb(51, 51, 255);"> 歡迎推薦一些開源的小系統,要求是能用,好用,方便,我有時間研究研究同時寫出使用心得,爲後來者快速入手帶來幫助。</span></strong></p><div><strong><span style="color: rgb(51, 51, 255);">
</span></strong></div>
  

發佈了32 篇原創文章 · 獲贊 2 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章