您现在的位置: 365建站网 > 365文章 > LINQ Expressions 动态生成委托——DataReader转换为List方法改进

LINQ Expressions 动态生成委托——DataReader转换为List方法改进

文章来源:365jz.com     点击数:556    更新时间:2009-09-13 10:54   参与评论

在上一篇《DataReader转换为List的一种实现》文章中我构建了一个IDataReader得扩展

</>code

  1. public static IEnumerable<T> GetEnumerator<T>(this IDataReader reader,Func<IDataRecord, T> generator)

这个扩展时接受一个委托类型的参数实现DataReader转换为对应的实体类,而这个委托所执行的方法便是下图的实现:

</>code

  1. public static QuestionNotifyInfo CreateQuestionNotifyInfo(IDataRecord record)
    {
    return new QuestionNotifyInfo
    {
    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")
    };
    }

如果项目中想要使用上一篇《DataReader转换为List的一种实现》文章中方案的话,每一个实体类都必须实现一个类似上图中的转换实体方法,虽然我们可以使用代码生成的方式

为每个类实现上诉方法,但不知为何,总是感觉这样的做法还是太机械,而且代码也太丑陋,为此必须寻找一种更好的方法。

观察所有实体类的转换方法,可以看出这些方法有类似的地方,可以抽象为如下的“模板”:

r => new T

{

    Property1 = r.Field<Type[Property1]>("Property1"),

    Property2 = r.Field<Type[Property2]>("Property2"),

   

}

 

能不能使用System.Linq.Expressions API中的方法动态生成这些方法呢?答案是肯定

结合我这里的实际情况实现的代码如下:

 

</>code

  1. public static Func<IDataRecord, T> DynamicCreateEntity<T>()
    {
    // Compiles a delegate of the form (IDataRecord r) => new T { Prop1 = r.Field<Prop1Type>("Prop1"), ... }
    ParameterExpression r = Expression.Parameter(typeof(IDataRecord), "r");

    // Create property bindings for all writable properties
    List<MemberBinding> bindings = new List<MemberBinding>();

    foreach (PropertyInfo property in (typeof(T).GetProperties()))
    {
    // Create expression representing r.Field<property.PropertyType>(property.Name)
    MethodCallExpression propertyValue = Expression.Call(
    typeof(DatabaseExtend).GetMethod("Field").MakeGenericMethod(property.PropertyType),
    r, Expression.Constant(property.Name));

    // Assign the property value to property through a member binding
    MemberBinding binding = Expression.Bind(property, propertyValue);
    bindings.Add(binding);
    }
    // Create the initializer, which instantiates an instance of T and sets property values

    // using the member bindings we just created
    Expression initializer = Expression.MemberInit(Expression.New(typeof(T)), bindings);

    // Create the lambda expression, which represents the complete delegate (r => initializer)
    Expression<Func<IDataRecord, T>> lambda = Expression.Lambda<Func<IDataRecord, T>>(
    initializer, r);

    return lambda.Compile();

    }

</>code

  1.  

有了上面的方法之后,现在我们必要为每个实体类都增加一个装换的方法了,所有现在我们可以更加简化我们的数据访问层的操作了,继续扩展数据库访问类,添加下面两个扩展方法:

</>code

  1. public static IList<T> ExecuteStoredProc<T>(this Database dataBase, string storedProcedureName, params object[] parameterValues)
    {
    IList<T> result = null;
    using (IDataReader dr=dataBase.ExecuteReaderStoredProc(storedProcedureName,parameterValues))
    {
    result = dr.GetEnumerator(DynamicCreateEntity<T>()).ToList();
    }
    return result;
    }
    public static IList<T> ExecuteSqlStringc<T>(this Database dataBase, string formatSqlString, params object[] parameterValues)
    {
    IList<T> result = null;
    using (IDataReader dr = dataBase.ExecuteReaderSqlString(formatSqlString, parameterValues))
    {
    result = dr.GetEnumerator(DynamicCreateEntity<T>()).ToList();
    }
    return result;
    }

 

主要参考文章 Using LINQ Expressions to Generate Dynamic Methods

Tag标签: asp.net,linq expressions,linq,委托,C#,DataReader

如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛

发表评论 (556人查看0条评论)
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
昵称:
最新评论
------分隔线----------------------------

快速入口

· 365软件
· 杰创官网
· 建站工具
· 网站大全

其它栏目

· 建站教程
· 365学习

业务咨询

· 技术支持
· 服务时间:9:00-18:00
365建站网二维码

Powered by 365建站网 RSS地图 HTML地图

copyright © 2013-2024 版权所有 鄂ICP备17013400号