我有一个对象,我想以这种方式构造:
var foo = new FancyObject(customer, c=>c.Email); //customer has Email property
Run Code Online (Sandbox Code Playgroud)
我该如何申报第二个参数?
访问所选属性setter/getter的代码如何?
UPD.模型中有多个实体具有Email属性.所以签名可能看起来像:
public FancyObject(Entity holder, Expression<Func<T>> selector)
Run Code Online (Sandbox Code Playgroud)
和构造函数调用
var foo = new FancyObject(customer, ()=>customer.Email);
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 104
参数将是一个Expression<Func<Customer,string>> selector.阅读它可以通过平面编译:
Func<Customer,string> func = selector.Compile();
Run Code Online (Sandbox Code Playgroud)
然后你就可以访问了func(customer).分配比较棘手; 对于简单的选择器,您可以希望您可以简单地分解为:
var prop = (PropertyInfo)((MemberExpression)selector.Body).Member;
prop.SetValue(customer, newValue, null);
Run Code Online (Sandbox Code Playgroud)
但是更复杂的表达式要么需要手动树遍,要么需要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();
Run Code Online (Sandbox Code Playgroud)
看起来类型必须是通用的两个类型参数 - 源和结果.例如,您可以使用:
var foo = new FancyObject<Customer, string>(customer, c => c.Email);
Run Code Online (Sandbox Code Playgroud)
第一个参数是类型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;
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用非泛型类型中的静态方法更简单:
var foo = FancyObject.Create(customer, c => c.Email);
Run Code Online (Sandbox Code Playgroud)
这可以使用类型推断来计算类型参数.
| 归档时间: |
|
| 查看次数: |
47965 次 |
| 最近记录: |