用反射实现将数据自动填充到对象中,学习orm的半个功能
2015-07-12 16:42
585 查看
最近整理以前的资料,想起来了这个小东西,以前感觉反射效率应该不行,后来翻看了nhibernate的源代码彻底改变了我的观点,随后自己动手写了这个小东西玩玩,大牛就不用看了,对反射有意思的可以瞧瞧
基本原理说明,我将业务类用自定义属性[CustAttribute]进行标注,然后用ado.net 获取数据集,将数据集中列名与对应业务类属性名称相同的进行填充操作,思路简单明了。
自定义CustAttribute类:
有如下Order业务类定义
需求是根据ID获取单个SaleOrder数据
如果没有DataRowClassMap 进行填充数据,那我就得用如下的方法敲代码,一个类还行,要是多了手酸眼花
基本原理说明,我将业务类用自定义属性[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业务类定义
publicclass 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 staticSaleOrder GetDataByID(Guid ID)
{
try
{
string sqlstr = string.Format("select top 1 * from Inv_SaleOrder whereID='{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="https://oscdn.geek-share.com/Uploads/Images/Content/201707/33c29e3268d66ef5c09858efe40a3635.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>
相关文章推荐
- 传值 & 传地址 & 传引用 解析
- Java运行时——反射
- BGP团体属性(实验)
- 使用Git、Git GUI和TortoiseGit
- UVA 644 Immediate Decodability
- 支持向量机的一种特征选取算法
- 移动开发、C/C++、算法、程序员人生
- 分离式LAMP平台构建
- Java 反射常用方法示例
- c中宏定义
- 神经网络的通俗理解
- DB2日常维护
- iOS基础(oc)-继承
- Docker初次使用记录
- Swift和OC混合编程
- HDU 2092 整数解
- Java反射的基础——Class类
- scikit-learn:0.1. 数据集格式和预测器
- ListView的item不能点击(焦点冲突问题)
- nova的手工安装