I am trying to create a delegate for setting a property value of a generic, but I am getting an error: Error binding to target method
when I try to execute the following code:
Action<T, object> setValue = (Action<T, object>) Delegate.CreateDelegate(
typeof(Action<T, object>), null, property.GetSetMethod());
Is this even possible?
Yes it is possible, you're just trying to create a delegate of the wrong type. The set method of a property only takes one argument, the value you're going to set. Also since its an instance method, you must pass the target object you want it to be bound to in the CreateDelegate call.
Example:
var setValue = (Action<T>)Delegate.CreateDelegate( typeof( Action<T> ), target, property.GetSetMethod() );
I think you want this:
Action<T, object> setValue = (t, o) => property.GetSetMethod().Invoke(t, new object[] { o });
or
Action<T, object> setValue = (t, o) => property.SetValue(t, o, null);
EDIT
To illustrate the assumed poorer performance of this answer compared to the accepted answer, assume this method:
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's answer uses reflection in the GetSetter
method, so we assume that the GetSetter
method takes more time to execute, in his approach. This answer uses reflection each time we call setValue.Invoke
, so we assume that takes more time to execute in this answer. If we assume the number of items in the sequence is large, MerickOWA's answer should require less time to execute.
For example, let's say that MerickOWA's GetSetter method takes X milliseconds more than mine to execute, while my setValue delegate takes Y milliseconds more than his. If there are N items in the sequence, then my solution should be slower than his by (N * Y - X) milliseconds.
It depends. In my answer I assume two things:
Because your property is a non-static, there are two possibilies:
A function to create such "normal" delegate is created as follows:
static public Action<TClass, TProperty> CreateSetPropertyDelegate<TClass, TProperty>(this PropertyInfo propertyInfo)
{
return (Action<TClass, TProperty>)Delegate.CreateDelegate(typeof(Action<TClass, TProperty>), propertyInfo.GetSetMethod());
}
And in use (assuming the property type is of type int):
Action<int> setter = typeof(MyClass).GetProperty("MyProperty").CreateSetPropertyDelegate<MyClass, int>(myInsance);
setter(myPropertyValue);
A function to create an open delegate:
static public Action<TClass, TProperty> CreateSetPropertyDelegate<TClass, TProperty>(this PropertyInfo propertyInfo)
{
return (Action<TClass, TProperty>)Delegate.CreateDelegate(typeof(Action<TClass, TProperty>), propertyInfo.GetSetMethod());
}
And in use:
Action<MyClass, int> setter = typeof(MyClass).GetProperty("MyProperty").CreateSetPropertyDelegate<MyClass, int>();
setter(myInsance, myPropertyValue);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With