【问题标题】:Delegate for Generic Property.GetSetMethod通用 Property.GetSetMethod 的委托
【发布时间】:2011-11-10 23:01:35
【问题描述】:

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

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

这可能吗?

【问题讨论】:

  • 您的属性是静态属性吗?如果不是,则不能传递 null。
  • 不,不是,很抱歉我错过了那篇文章,但即使我传入类的一个实例,它也不能正常工作,我仍然会遇到同样的异常

标签: c# generics delegates


【解决方案1】:

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

例子:

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

【讨论】:

    【解决方案2】:

    我想你想要这个:

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

    【讨论】:

    • 每次都使用 PropertyInfo 设置值,这比 CreateDelegate 返回的要慢得多
    • 你能告诉我为什么这个方法会更慢吗?在我的测试中,lambda 的执行时间是创建委托的一半。
    • @nawfal 因为使用这种技术,setValue 是对使用反射的委托的引用,该委托使用它设置属性值的另一个委托。每次调用 setValue 的引用时,您都在使用反射 API。接受的答案中的方法使用反射来创建直接设置属性的委托,因此当您分配 setValue 时,您使用了一次反射 API; setValue 的调用不使用反射。
    • @phoog 但为什么我的答案是你的答案而不是 MerickOWA 的?还是我应该把它作为一个单独的问题?
    • @nawfal 我在我的答案中添加了性能讨论,部分是为了澄清“分配 setValue 变量”和“调用其所指对象”之间的区别。
    【解决方案3】:

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

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

    创建开放委托的函数:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多