1

我有这个代码:

public static Func<IDataReader, T> CreateBinder<T>() {

    NewExpression dataTransferObject = Expression.New(typeof(T).GetConstructor(Type.EmptyTypes)); 
    ParameterExpression dataReader = Expression.Parameter(typeof(IDataReader), "reader");

    IEnumerable<Expression> columnAssignments = typeof(T).GetProperties().Select(property => {
        MethodCallExpression columnData = Expression.Call(dataReader, dataReaderIndexer, new[] { Expression.Constant(property.Name) });
        MethodCallExpression setter = Expression.Call(dataTransferObject, property.SetMethod, new[] { Expression.Convert( columnData, property.PropertyType ) });

        return setter;
    });

    columnAssignments = columnAssignments.Concat(new Expression[] { dataTransferObject });
    BlockExpression assignmentBlock = Expression.Block(columnAssignments);

    Func<IDataReader, T> binder = Expression.Lambda<Func<IDataReader, T>>(assignmentBlock, new[] { dataReader }).Compile();

    return binder;
}

长话短说将数据库行上的属性绑定到<T>. 问题是当我想使用/返回时dataTransferObject,它每次都实例化一个新副本。如何在不重新创建对象的情况下获取参考?

4

2 回答 2

3

您只需要将 分配NewExpression给一个变量,然后使用该变量而不是NewExpression.

var dataTransferObject = Expression.Variable(typeof(T), "dto");
var assignment = Expression.Assign(
                     dataTransferObject,
                     Expression.New(typeof(T).GetConstructor(Type.EmptyTypes)));

(将这些表达式添加到BlockExpression

于 2013-07-29T18:29:39.137 回答
3

我建议使用成员初始化/绑定表达式而不是一系列设置器:

public static Func<IDataReader, T> CreateBinder<T>() 
{
    NewExpression dataTransferObject = Expression.New(typeof(T).GetConstructor(Type.EmptyTypes)); 
    ParameterExpression dataReader = Expression.Parameter(typeof(IDataReader), "reader");

    IEnumerable<MemberBinding > bindings = typeof(T).GetProperties().Select(property => {
        MethodCallExpression columnData = Expression.Call(dataReader, dataReaderIndexer, new[] { Expression.Constant(property.Name) });
        MemberBinding binding = Expression.Binding(property, Expression.Convert( columnData, property.PropertyType));

        return binding;
    });

    Expression init = Expression.MemberInit(dataTransferObject, bindings);

    Func<IDataReader, T> binder = Expression.Lambda<Func<IDataReader, T>>(init, new[] { dataReader }).Compile();

    return binder;
}
于 2013-07-29T18:30:43.610 回答