你如何对NewExpression进行引用?

时间:2013-07-29 18:19:36

标签: c# expression-trees

我有这段代码:

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>。问题是,当我想使用/ return dataTransferObject时,它每次都会实例化一个新副本。如何在不重新创建对象的情况下获取引用?

2 个答案:

答案 0 :(得分:3)

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

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

(将这些表达式添加到BlockExpression

答案 1 :(得分:3)

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

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;
}