委托Generic Property.GetSetMethod

我正在尝试创建一个委托来设置generics的属性值,但我收到一个错误:当我尝试执行以下代码时Error binding to target method

 Action setValue = (Action) Delegate.CreateDelegate( typeof(Action), null, property.GetSetMethod()); 

这有可能吗?

是的,有可能,你只是想创建一个错误类型的委托。 属性的set方法只接受一个参数,即您要设置的值。 此外,由于它是一个实例方法,您必须在CreateDelegate调用中传递您希望它绑定到的目标对象。

例:

  var setValue = (Action)Delegate.CreateDelegate( typeof( Action ), target, property.GetSetMethod() ); 

我想你想要这个:

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

要么

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

编辑

为了说明这个答案假定的较差的表现与接受的答案相比,假设这种方法:

 void SetAnObjectPropertyOnALotOfObjects(IEnumerable objs) { //Create a delegate and assign a reference to that delegate to the setValue variable Action 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方法中使用了reflection,因此我们假设GetSetter方法在他的方法中需要更多的时间来执行。 这个答案每次调用setValue.Invoke时都使用reflection,所以我们假设在这个答案中需要更多的时间来执行。 如果我们假设序列中的项目数量很大,那么MerickOWA的答案应该需要更少的时间来执行。

例如,假设MerickOWA的GetSetter方法比我的执行需要X毫秒多,而我的setValue委托比他的需要花费Y毫秒。 如果序列中有N个项目,那么我的解决方案应该比他的(N * Y – X)毫秒慢。

这取决于。 在我的回答中,我假设有两件事:

  1. 您的类型“T”是您的类的类型(我现在将其称为TClass)
  2. 类型“对象”是您的属性的类型(我现在将其称为TProperty)

因为您的属性是非静态的,所以有两种可能性:

  1. 附加目标(实例)的“普通”委托。
  2. 一个“开放”委托,其中需要一个目标作为委托的第一个输入参数。

创建这样的“普通”委托的函数创建如下:

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

并在使用中(假设属性类型为int类型):

 Action setter = typeof(MyClass).GetProperty("MyProperty").CreateSetPropertyDelegate(myInsance); setter(myPropertyValue); 

一个创建开放委托的函数:

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

并在使用中:

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