我有这段代码:
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
时,它每次都会实例化一个新副本。如何在不重新创建对象的情况下获取引用?
答案 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;
}