2011-01-14 94 views
2

我所試圖做的似乎很簡單,但我不能找到一種方法。讓我們假設我有這個簽名的方法:Func鍵<>值賦給結果

public void Foo<T,K>(Expression<Func<T,K>> binding, T item, K value) 

我想我的方法裏面做的是:應用Func鍵項,獲得K型的到的屬性綁定表達式點,並指定「價值「。

如果綁定表達式是一樣的東西:

c => c.Property 

其中「C」是「T」和「財產」是「K」,我可以輕鬆地使用一些反思,並使用字段信息設定值。下面的代碼工作:

(((binding as LambdaExpression).Body as MemberExpression).Member as FieldInfo).SetValue(item, value); 

但表達可能是這樣的:

c => c.SubClass.Property 

c => c.SubClass1.SubClass2.SubClassN.Property 

在這種情況下,反射代碼不起作用,因爲「物權「不直接屬於T,但它仍然是該方法簽名的有效lambda表達式。

我知道,如果我編譯Func並在我的TI類型的項目上運行它,那麼它就像它的「副本」,而不是它的引用,所以即使將值賦給它,原始項目上的屬性不會更改。

如果任何人有一個乾淨的解決方案,這一點,或者只是點我的東西,能給予我表達式樹有更好的認識,你是非常歡迎。

+1

你 '複製' 的假設是唯一有效的,如果有在 '鏈' 一'struct`地方。對於參考類型,分配會很好。 – leppie 2011-01-14 17:26:21

+0

我期待的很多,但我試過了,並沒有奏效。 「子類」都是「類」,所以引用類型,以及T.即使我正在嘗試做的最終屬性是一個類,所以引用類型。 – 2011-01-14 18:47:39

回答

3

這聽起來像你真的不希望從T一「K」,而是要A K分配是t知道一個K,對不對?

public void Foo<T,K>(Action<T,K> binding, T item, K value) 
{ 
    binding(item, value); 
} 

似乎更正確的,因爲結合是可以採取T和告訴噸至做正確的事與K,右一個委託?像這樣稱呼它?

Foo<T,K>((t, k) => t.SubClass.Property = k, aT, aK); 
+1

這正是我所需要的,而且確實是微不足道的,但在辦公室工作的繁忙,我不能去想它。過去我曾多次使用Action <>。傻我。非常感謝,你救了我的一天。 – 2011-01-14 18:59:18

1
static void AssignValue<TSource, TResult>(Expression<Func<TSource, TResult>> expression, TSource source, TResult result) 
{ 
    var paramExp = expression.Parameters.Single(); 
    var assignExp = Expression.Assign(expression.Body, Expression.Constant(result)); 
    var lambdaExp = Expression.Lambda(assignExp, paramExp); 
    lambdaExp.Compile().DynamicInvoke(source); 
} 

用法:

class Product 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
} 

var product = new Product { ID = 99, Name = "haha" }; 
AssignValue<Product, string>(p => p.Name, product, "changed"); 
相關問題