我有一个对象,我想以这种方式构造它:
var foo = new FancyObject(customer, c=>c.Email); //customer has Email property
我应该如何声明第二个参数?
访问所选属性setter/getter的代码将是什么样子?
Upd。模型中有几个具有电子邮件属性的实体。因此,签名可能如下所示:
public FancyObject(Entity holder, Expression<Func<T>> selector)
和构造函数调用
var foo = new FancyObject(customer, ()=>customer.Email);
发布于 2011-02-22 16:06:01
该参数将是一个Expression<Func<Customer,string>> selector
。读取它可以通过平面编译:
Func<Customer,string> func = selector.Compile();
然后你就可以访问func(customer)
了。赋值是比较棘手的;对于简单的选择器,你可以希望你可以简单地分解成:
var prop = (PropertyInfo)((MemberExpression)selector.Body).Member;
prop.SetValue(customer, newValue, null);
但更复杂的表达式要么需要手动遍历树,要么需要一些4.0表达式节点类型:
Expression<Func<Customer, string>> email
= cust => cust.Email;
var newValue = Expression.Parameter(email.Body.Type);
var assign = Expression.Lambda<Action<Customer, string>>(
Expression.Assign(email.Body, newValue),
email.Parameters[0], newValue);
var getter = email.Compile();
var setter = assign.Compile();
发布于 2011-02-22 15:58:43
看起来该类型必须是具有两个类型参数的泛型-- source和result。例如,您可以使用:
var foo = new FancyObject<Customer, string>(customer, c => c.Email);
第一个参数的类型为TSource
,第二个参数的类型为Expression<Func<TSource, TResult>>
public class FancyObject<TSource, TResult>
{
private readonly TSource value;
private readonly Expression<Func<TSource, TResult>> projection;
public FancyObject(TSource value,
Expression<Func<TSource, TResult>> projection)
{
this.value = value;
this.projection = projection;
}
}
通过使用非泛型类型中的静态方法,可以使这一点更简单:
var foo = FancyObject.Create(customer, c => c.Email);
可以使用类型推断来计算类型参数的。
https://stackoverflow.com/questions/5075484
复制相似问题