C# 泛型属性的委托。GetSetMethod

C# 泛型属性的委托。GetSetMethod,c#,generics,delegates,C#,Generics,Delegates,我正在尝试创建一个委托来设置泛型的属性值,但在尝试执行以下代码时遇到错误:错误绑定到目标方法: Action<T, object> setValue = (Action<T, object>) Delegate.CreateDelegate( typeof(Action<T, object>), null, property.GetSetMethod()); Action setValue=(Action)Delegate.CreateDelegat

我正在尝试创建一个委托来设置泛型的属性值,但在尝试执行以下代码时遇到错误:
错误绑定到目标方法

Action<T, object> setValue = (Action<T, object>) Delegate.CreateDelegate(
    typeof(Action<T, object>), null, property.GetSetMethod());
Action setValue=(Action)Delegate.CreateDelegate(
typeof(Action),null,property.GetSetMethod());
这可能吗?

我想你想要这个:

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

Action 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());
    }
}
void SetAnObjectPropertyOnALotOfObjects(IEnumerable objs)
{
//创建一个委托,并将对该委托的引用指定给setValue变量
Action setValue=GetSetter();
foreach(objs中的var o)
{
//调用setValue变量引用的委托(即“调用其引用对象”
调用(o,新对象());
}
}
MerickOWA的答案在
GetSetter
方法中使用反射,因此我们假设在他的方法中
GetSetter
方法需要更多的时间来执行。这个答案在每次调用
setValue.Invoke
时都使用反射,因此我们假设在这个答案中执行需要更多的时间。如果我们假设由于顺序很大,梅里科娃的回答应该需要较少的时间来执行


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

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

例如:

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

视情况而定。在我的回答中,我假设有两件事:

  • 您的类型“T”是您的类的类型(我现在将其表示为TClass)
  • 类型“object”是您的属性的类型(我现在将其表示为TProperty)
  • 因为您的属性是非静态的,所以有两种可能:

  • 附加了目标(实例)的“普通”委托
  • 一种“打开”委托,其中要求将目标作为委托的第一个输入参数
  • 创建此类“正常”委托的函数如下所示:

    static public Action<TClass, TProperty> CreateSetPropertyDelegate<TClass, TProperty>(this PropertyInfo propertyInfo)
    {
        return (Action<TClass, TProperty>)Delegate.CreateDelegate(typeof(Action<TClass, TProperty>), propertyInfo.GetSetMethod());
    }
    
    静态公共操作CreateSetPropertyLegate(此PropertyInfo PropertyInfo)
    {
    return(Action)Delegate.CreateDelegate(typeof(Action),propertyInfo.GetSetMethod());
    }
    
    和正在使用中(假设属性类型为int类型):

    Action setter=typeof(MyClass).GetProperty(“MyProperty”).CreateSetPropertyDelegate(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());
    }
    
    静态公共操作CreateSetPropertyLegate(此PropertyInfo PropertyInfo)
    {
    return(Action)Delegate.CreateDelegate(typeof(Action),propertyInfo.GetSetMethod());
    }
    
    在使用中:

    Action<MyClass, int> setter = typeof(MyClass).GetProperty("MyProperty").CreateSetPropertyDelegate<MyClass, int>();
    setter(myInsance, myPropertyValue);
    
    Action setter=typeof(MyClass).GetProperty(“MyProperty”).CreateSetPropertyDelegate();
    setter(myInsance,myPropertyValue);
    
    你的属性是静态属性吗?如果不是,那么你不能传递null。不是,很抱歉我错过了那一部分,但是即使我传递类的实例,它也不能正常工作,我仍然会得到相同的例外情况。每次都使用PropertyInfo设置值,这比CreateDelegate返回的要慢得多。你能告诉我吗告诉我为什么这个方法会慢一些?在我的测试中,lambda的执行时间只有create delegate的一半。@nawfal因为使用这种技术,
    setValue
    是对一个委托的引用,该委托使用反射来获取另一个委托,并用它来设置属性值。每次调用
    setValue
    的referent时,您都在使用反射API。接受答案中的方法使用反射来创建直接设置属性的委托,因此在分配
    setValue
    时只使用了一次反射API;
    setValue
    的调用不使用反射。@phoog但是为什么我用你的答案而不是MerickOWA的答案来提高性能呢?Or我应该把它作为一个单独的问题吗?@nawfal我在我的回答中添加了一个性能讨论,部分是为了澄清“分配setValue变量”和“调用其引用对象”之间的区别。
    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);