遍历Linq表达式以设置属性字段的值

时间:2010-09-02 06:33:27

标签: c# linq expression-trees

这是一个非常复杂的问题,即使看起来很简单。我想我必须遍历整个表达式树,除非有人知道更好的方法。

假设我有一个用户对象

class User
{
    public UserAccount Account {get;set;}
}
class UserAccount
{
    public Name {get;set;}
}
var user = new User() { Account = new UserAccount()};

我如何使用linq表达式设置Name

的属性
SetValue(c => c.Account.Name, "Test");

2 个答案:

答案 0 :(得分:2)

好吧,你不仅需要遍历表达式树:你还必须将遇到的最终属性“getter”转换为属性“setter”。基本上你想要找到充当getter“目标”的表达式(即它将获取属性的对象),计算它以获取目标,然后为最终属性找到相应的setter,并且用目标和新值来称呼它。

请注意,只需要表达式树来表示“getter”,你就会失去一些你可能期望的编译时安全性......因为调用者可以传入一个只读属性:

SetValue(c => c.Account.Name.Length, 0); // string.Length is read-only

另一种方法是更改​​代码,使lambda表达式代表setter:

SetValue((c, value) => c.Account.Name = value, "Test");

然后你甚至不需要表达式树 - 你可以使用一个简单的委托,只需适当地执行它。

不幸的是,你并没有真正向我们提供足够的信息,告诉我们你想要了解的是否这是一个可行的建议。

答案 1 :(得分:1)

是的,您必须遍历整个表达式树,如果您想在一般情况下工作,可能会遇到挑战。你不能这样做:

SetValue<User>(c => c.Account.Name = "Test");

SetValue的定义如下:

public void SetValue<T>(Action<T> action)
{
    ...
}

或者没有通用参数,如果这只适用于User