LINQ Expressions 动态生成委托——DataReader转换为List方法改进
2009-08-21 15:37
405 查看
在上一篇《DataReader转换为List的一种实现》文章中我构建了一个IDataReader得扩展
这个扩展时接受一个委托类型的参数实现DataReader转换为对应的实体类,而这个委托所执行的方法便是下图的实现:
如果项目中想要使用上一篇《DataReader转换为List的一种实现》文章中方案的话,每一个实体类都必须实现一个类似上图中的转换实体方法,虽然我们可以使用代码生成的方式
为每个类实现上诉方法,但不知为何,总是感觉这样的做法还是太机械,而且代码也太丑陋,为此必须寻找一种更好的方法。
观察所有实体类的转换方法,可以看出这些方法有类似的地方,可以抽象为如下的“模板”:
r=>newT
{
Property1=r.Field<Type[Property1]>("Property1"),
Property2=r.Field<Type[Property2]>("Property2"),
…
}
能不能使用System.Linq.ExpressionsAPI中的方法动态生成这些方法呢?答案是肯定
结合我这里的实际情况实现的代码如下:
有了上面的方法之后,现在我们必要为每个实体类都增加一个装换的方法了,所有现在我们可以更加简化我们的数据访问层的操作了,继续扩展数据库访问类,添加下面两个扩展方法:
主要参考文章UsingLINQExpressionstoGenerateDynamicMethods
publicstaticIEnumerable<T>GetEnumerator<T>(thisIDataReaderreader,Func<IDataRecord,T>generator)
这个扩展时接受一个委托类型的参数实现DataReader转换为对应的实体类,而这个委托所执行的方法便是下图的实现:
publicstaticQuestionNotifyInfoCreateQuestionNotifyInfo(IDataRecordrecord) { returnnewQuestionNotifyInfo { QID=record.Field<int>("QID"), Title=record.Field<string>("Title"), AnswerID=record.Field<int>("AnswerID"), UserID=record.Field<int>("UserID"), UserName=record.Field<string>("UserName"), Content=record.Field<string>("Content"), DateAdded=record.Field<DateTime>("DateAdded"), NotifyType=record.Field<int>("NotifyType") }; }
如果项目中想要使用上一篇《
为每个类实现上诉方法,但不知为何,总是感觉这样的做法还是太机械,而且代码也太丑陋,为此必须寻找一种更好的方法。
观察所有实体类的转换方法,可以看出这些方法有类似的地方,可以抽象为如下的“模板”:
r=>newT
{
Property1=r.Field<Type[Property1]>("Property1"),
Property2=r.Field<Type[Property2]>("Property2"),
…
}
能不能使用System.Linq.ExpressionsAPI中的方法动态生成这些方法呢?答案是肯定
结合我这里的实际情况实现的代码如下:
publicstaticFunc<IDataRecord,T>DynamicCreateEntity<T>() { //Compilesadelegateoftheform(IDataRecordr)=>newT{Prop1=r.Field<Prop1Type>("Prop1"),...} ParameterExpressionr=Expression.Parameter(typeof(IDataRecord),"r"); //Createpropertybindingsforallwritableproperties List<MemberBinding>bindings=newList<MemberBinding>(); foreach(PropertyInfopropertyin(typeof(T).GetProperties())) { //Createexpressionrepresentingr.Field<property.PropertyType>(property.Name) MethodCallExpressionpropertyValue=Expression.Call( typeof(DatabaseExtend).GetMethod("Field").MakeGenericMethod(property.PropertyType), r,Expression.Constant(property.Name)); //Assignthepropertyvaluetopropertythroughamemberbinding MemberBindingbinding=Expression.Bind(property,propertyValue); bindings.Add(binding); } //Createtheinitializer,whichinstantiatesaninstanceofTandsetspropertyvalues //usingthememberbindingswejustcreated Expressioninitializer=Expression.MemberInit(Expression.New(typeof(T)),bindings); //Createthelambdaexpression,whichrepresentsthecompletedelegate(r=>initializer) Expression<Func<IDataRecord,T>>lambda=Expression.Lambda<Func<IDataRecord,T>>( initializer,r); returnlambda.Compile(); }
有了上面的方法之后,现在我们必要为每个实体类都增加一个装换的方法了,所有现在我们可以更加简化我们的数据访问层的操作了,继续扩展数据库访问类,添加下面两个扩展方法:
publicstaticIList<T>ExecuteStoredProc<T>(thisDatabasedataBase,stringstoredProcedureName,paramsobject[]parameterValues)
{
IList<T>result=null;
using(IDataReaderdr=dataBase.ExecuteReaderStoredProc(storedProcedureName,parameterValues))
{
result=dr.GetEnumerator(DynamicCreateEntity<T>()).ToList();
}
returnresult;
}
publicstaticIList<T>ExecuteSqlStringc<T>(thisDatabasedataBase,stringformatSqlString,paramsobject[]parameterValues)
{
IList<T>result=null;
using(IDataReaderdr=dataBase.ExecuteReaderSqlString(formatSqlString,parameterValues))
{
result=dr.GetEnumerator(DynamicCreateEntity<T>()).ToList();
}
returnresult;
}
主要参考文章
相关文章推荐
- ASM(六) 利用TreeApi 动态生成以及转换方法字节码
- <转>根据泛型生成数组 与数组 List相互转换的方法
- 对ASP动态包含文件方法的改进
- 关于数组和list之间相互转换的方法
- ABAP 动态生成内表的几种方法
- C#中自定义方法,动态编译,生成dll文件
- JS动态生成元素鼠标响应方法 .live()
- 从异常{ 无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型 }说开去
- 数组和List之间相互转换的方法
- php动态生成缩略图并输出显示的方法
- [jquery] 给动态生成的元素绑定事件 on方法
- 动态生成RSS文件的方法。
- 动态生成树型结构方法
- Angular JS 生成动态二维码的方法
- ResultSet转换为List的方法
- Python动态生成多维数组的方法示例
- C# IList转换为datatable的方法
- jquery动态生成的元素添加事件的方法
- jQuery为动态生成的select元素添加事件的方法
- 还是一个动态生成列的问题,比较彻底的解决方法(MVP思归)