泛型属性的委托

本文关键字:属性 泛型 | 更新日期: 2023-09-27 18:14:14

我试图创建一个用于设置泛型属性值的委托,但我得到一个错误:Error binding to target method时,我尝试执行以下代码:

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

这可能吗?

泛型属性的委托

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

的例子:

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

看情况。在我的回答中,我假设了两件事:

  1. 你的类型"T"是你的类的类型(我现在将其表示为TClass)
  2. 类型"object"是你的属性的类型(我现在将其标记为TProperty)

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

  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);

创建open委托的函数:

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);

我想你想要这个:

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)毫秒。