用反射实现将数据自动填充到对象中,学习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>
  

如果您觉得我的文章对您有所帮助,欢迎扫码进行赞赏!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌晨4点5杀老大爷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值