2010-09-02 81 views
2

儘管看起來很簡單,但這是一個非常複雜的問題。我想我必須遍歷整個表達式樹,除非有人知道更好的方法。遍歷Linq表達式來設置屬性字段的值

比方說,我有一個用戶對象

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

我怎麼能使用LINQ表達式來設置名稱的屬性

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

這與ASP.NET有什麼關係? – 2010-09-02 06:36:10

+0

我正在使用asp.net的事實 – Kyle 2010-09-02 06:43:21

回答

2

好了,你不僅要遍歷表達式樹:你還必須將遇到的最終財產「getter」轉換爲財產「setter」。基本上,你會希望找到充當吸氣劑「目標」的表達式(即它將獲得屬性的對象),評估它以獲得目標,然後找到最終屬性的對應設置器,以及用目標和新值調用它。

請注意,只需要表達式樹來表示「getter」,就會失去一些編譯時安全性,因爲調用者可能會傳入只讀屬性:

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

另一種方法是改變你的代碼,以使lambda表達式代表,而不是制定者:

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

然後,你甚至不需要一個表達式樹 - 你可以使用一個簡單的委託,只是適當地執行它。

不幸的是,您並沒有真正向我們提供足夠的有關您想要實現的信息,以瞭解這是否是可行的建議。

+0

這是一個有趣的改變,但它會使我的代碼不那麼明確。 – Kyle 2010-09-02 06:42:22

+0

我不知道我是否可以修改樹... – Kyle 2010-09-02 06:45:46

+0

@Kyle:你不能修改表達式樹,但你可能會建立一個新的表達式樹。 – 2010-09-02 06:57:36

1

是的,你將不得不遍歷整個表達式樹,如果你想在一般情況下工作可能是具有挑戰性的。你就不能這樣做,而不是:

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

SetValue的定義是這樣的:

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

或者沒有,如果這隻會與User工作泛型參數。