2011-11-10 67 views
6

我試圖創建一個委託設置一個通用的屬性值,但我得到一個錯誤:當我嘗試執行以下代碼Error binding to target method委託通用Property.GetSetMethod

Action<T, object> setValue = (Action<T, object>) Delegate.CreateDelegate(
    typeof(Action<T, object>), null, property.GetSetMethod()); 

是這甚至有可能嗎?

+0

是你的屬性的一個靜態屬性?如果不是,那麼你不能傳遞null。 – phoog

+0

不,這不是,對不起,我錯過了一塊,但即使當我通過在類的實例,它不能正常工作,我仍然得到同樣的異常 – ChandlerPelhams

回答

3

是的,這是可能的,你只是試圖創建一個錯誤類型的委託。屬性的set方法只需要一個參數,即你要設置的值。另外,因爲它是一個實例方法,所以你必須在CreateDelegate調用中傳遞你想要綁定的目標對象。

實施例:

var setValue = (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), target, property.GetSetMethod()); 
1

我想你想要這樣的:

Action<T, object> setValue = (t, o) => property.GetSetMethod().Invoke(t, new object[] { o }); 

Action<T, object> setValue = (t, o) => property.SetValue(t, o, null); 

編輯

爲了說明這個答案比接受的答案的假設性能較差,假設這種方法:

void SetAnObjectPropertyOnALotOfObjects<T>(IEnumerable<T> objs) 
{ 
    //Create a delegate and assign a reference to that delegate to the setValue variable 
    Action<T, object> setValue = GetSetter(); 

    foreach (var o in objs) 
    { 
     //invoke the delegate referred to by the setValue variable (that is, "invoke its referent" 
     setValue.Invoke(o, new object()); 
    } 
} 

MerickOWA的答案使用了GetSetter方法中的反思,因此我們假設GetSetter方法在他的方法中需要更多時間來執行。每次我們呼叫setValue.Invoke時,這個答案都會使用反射,所以我們假設在這個答案中需要更多時間來執行。如果我們假設序列中的項目數量很大,MerickOWA的答案應該需要較少的時間來執行。例如,假設MerickOWA的GetSetter方法需要比我的執行時間多X毫秒,而我的setValue委託需要比他多Y毫秒。如果序列中有N個項目,那麼我的解決方案應該比他的(N * Y - X)毫秒慢。

+0

它使用的PropertyInfo每一次設置的值,這是慢得多比CreateDelegate會返回 – MerickOWA

+0

啊,當然(拍我的頭) – phoog

+0

你能告訴我爲什麼這種方法會變慢嗎?在我的測試中,lambda執行創建委託的一半時間。 – nawfal

1

這取決於。在我的答案我想兩件事情:

  1. 你的「T」型是你的類的類型(我現在記爲TClass)
  2. 類型「對象」是你的財產的類型(我現在記爲TProperty)

因爲你的財產是一個非靜態,有兩個possibilies:

  1. 一個「正常」的代表附有目標(實例)。
  2. 一個「開放」委託,其中需要一個目標作爲委託的第一個輸入參數。

來創建這樣的 「正常」 代表的函數被創建如下:

static public Action<TClass, TProperty> CreateSetPropertyDelegate<TClass, TProperty>(this PropertyInfo propertyInfo) 
{ 
    return (Action<TClass, TProperty>)Delegate.CreateDelegate(typeof(Action<TClass, TProperty>), propertyInfo.GetSetMethod()); 
} 

並且在使用中(假設屬性類型的類型是int):

Action<int> setter = typeof(MyClass).GetProperty("MyProperty").CreateSetPropertyDelegate<MyClass, int>(myInsance); 
setter(myPropertyValue); 

的函數創建公開委託:

static public Action<TClass, TProperty> CreateSetPropertyDelegate<TClass, TProperty>(this PropertyInfo propertyInfo) 
{ 
    return (Action<TClass, TProperty>)Delegate.CreateDelegate(typeof(Action<TClass, TProperty>), propertyInfo.GetSetMethod()); 
} 

並正在使用中:

Action<MyClass, int> setter = typeof(MyClass).GetProperty("MyProperty").CreateSetPropertyDelegate<MyClass, int>(); 
setter(myInsance, myPropertyValue);