续上两篇文章,使用emit构造dynamic method,把 datareader转换为实体,以免直接使用反射来实现带来的性能损失。代码看似没有纰漏,可是实际上我在framwork4下运行时,调用 dynamic method时,sql
系统都会报 “ 找不到方法 ‘?’ ”的错误,没有找到问题所在,网上查了下资料,发如今framwork3.5以上还能够用表达式树动态构造 执行的语句,并动态编译成方法。性能上与emit仍是接近,,并且代码精简了许多。express
废话很少说,上代码框架
public class EntityConverter { public static Action<T, object> GetSetter<T>(PropertyInfo property) { Action<T, object> result = null; Type type = typeof(T); string key = type.AssemblyQualifiedName + "_set_" + property.Name; if (HttpRuntime.Cache.Get(key) == null) { //建立 对实体 属性赋值的expression ParameterExpression parameter = Expression.Parameter(type, "t"); ParameterExpression value = Expression.Parameter(typeof(object), "propertyValue"); MethodInfo setter = type.GetMethod("set_" + property.Name); MethodCallExpression call = Expression.Call(parameter, setter, Expression.Convert(value, property.PropertyType)); var lambda = Expression.Lambda<Action<T, object>>(call, parameter, value); result = lambda.Compile(); HttpRuntime.Cache[key] = result; } else { result = HttpRuntime.Cache[key] as Action<T, object>; } return result; } public static List<T> ToList<T>(DataTable dt) where T : new() { List<T> list = new List<T>(); if (dt == null || dt.Rows.Count == 0) { return list; } foreach (DataRow dr in dt.Rows) { T t= new T(); foreach (PropertyInfo prop in typeof(T).GetProperties()) { if (dr.Table.Columns.Contains(prop.Name)) { GetSetter<T>(prop)(t, dr[prop.Name]); } } list.Add(t); } return list; } public static List<T> ToList<T>(IDataReader dr) where T:new() { List<T> list = new List<T>(); while (dr.Read()) { T t = new T(); foreach (PropertyInfo prop in typeof(T).GetProperties()) { GetSetter<T>(prop)(t, dr[prop.Name]); } list.Add(t); } return list; } }
代码还稍微有点粗糙,还能够细化一下,好比 datatable和datareader的字段名称,和对应实体的属性名,能够忽略大小写,目前个人代码是区分的,有兴趣的能够本身优化。性能
若是你看完了我写的文字还代码,仍是一头雾水,能够看看个人上两篇博文。简单说 就是相似orm的核心功能,把经过ado.net组件查询到的数据(datatable,datareader)转换为实体列表 List<T>,优化
若是你的代码框架还比较古老,又不肯意引入诸如EF,Nhibernate那样的比较大的框架,不妨考虑本身写一个这样的简单的方法。.net
List<T> list; using (IDataReader dr = sqlCommand.ExecuteReader(sql) { list = EntityConverter.ToList<T>(dr); }