C# 属性选择器表达式<;Func<;T>>;。如何获取/设置选定属性的值

C# 属性选择器表达式<;Func<;T>>;。如何获取/设置选定属性的值,c#,C#,我有一个对象,我希望以这样的方式构造: var foo = new FancyObject(customer, c=>c.Email); //customer has Email property 我应该如何声明第二个参数 访问所选属性setter/getter的代码是什么样子的 Upd。模型中有多个实体具有电子邮件属性。因此,签名可能看起来像: public FancyObject(Entity holder, Expression<Func<T>> selec

我有一个对象,我希望以这样的方式构造:

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, string>(customer, c => c.Email);
在非泛型类型中使用静态方法时,可以简化此操作:

var foo = FancyObject.Create(customer, c => c.Email);

它可以使用类型推断来计算类型参数。

该参数将是一个
表达式选择器。可以通过平面编译来读取:

 Func<Customer,string> func = selector.Compile();
但更复杂的表达式可能需要手动树漫游,也可能需要一些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();
Expression电子邮件
=客户=>客户电子邮件;
var newValue=Expression.Parameter(email.Body.Type);
var assign=Expression.Lambda(
表达式.Assign(email.Body,newValue),
email.Parameters[0],newValue);
var getter=email.Compile();
var setter=assign.Compile();

谢谢。那么访问所选属性如何?@jonskeet只是出于对该实例的兴趣,如何使用投影?我很感兴趣,因为我知道你可以用一个Func做类似的事情,然后调用Func.Invoke()来获取值。@MrEdmundo:你可以在LINQ to SQL中使用它,例如。。。您不能使用Func的地方。@JonSkeet谢谢,在这种情况下,执行表达式的正确方式是什么(我对表达式不熟悉)。@MrEdmundo:老实说,这完全取决于您试图用它做什么。这是一个太宽泛的问题,我无法回答。谢谢你,马克,我想这将是一个很好的例子,asumng类将有乔恩建议的{public class FancyObject}泛型。@Neo不,这不是“更正确”-只是“不那么直接”;对不起,我非常理解
表达式
API。我可以满足于
email.Parameters.Single()
,但是:上面的版本很好。我正在尝试将您的代码与
Expression.Lambda
(而不是
string
)一起使用,这样我就可以在各种类型的表达式对集合上通用地使用代码。但是,当属性的类型为
字符串时,出现错误“类型为'System.String'的ParameterExpression不能用于类型为'System.Object'的委托参数”。我想除了
对象
之外,任何其他类型的对象都会出现这种情况。你知道如何让这段代码在这种情况下工作吗?@Neo你必须使用Expression.Convert,这是一种通用的castYes,我发现了这个:但是,我无法让它工作,所以我刚刚提出了一个问题:如果你能看一下,我将非常感激……)
 Func<Customer,string> func = selector.Compile();
var prop = (PropertyInfo)((MemberExpression)selector.Body).Member;
prop.SetValue(customer, newValue, null);
        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();