【问题标题】:Example : Speeding up Reflection API with delegate in .NET/C#示例:在 .NET/C# 中使用委托加速反射 API
【发布时间】:2011-06-21 19:22:38
【问题描述】:

正如post 中所问的那样,我想出了一个使用 Delegate 加速 .NET/C# 中的反射的示例。

但是,我在运行时遇到了这个错误(编译工作正常)。可能有什么问题?

Unhandled Exception: System.ArgumentException: type is not a subclass of Multicastdelegate
  at System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method, Boolean throwOnBindFailure, Boolean allowClosed) [0x00000] in <filename unknown>:0 
  at System.Delegate.CreateDelegate (System.Type type, System.Reflection.MethodInfo method, Boolean throwOnBindFailure) [0x00000] in <filename unknown>:0 
  at System.Delegate.CreateDelegate (System.Type type, System.Reflection.MethodInfo method) [0x00000] in <filename unknown>:0 
  at EX.RefTest.DelegateTest () [0x00000] in <filename unknown>:0 
  at EX.RefTest.Main () [0x00000] in <filename unknown>:0 

添加

感谢 Jon 和 ChaosPandion 的帮助,这是(工作的)源代码。

using System.Reflection;
using System;

namespace EX
{
    public class Hello
    {
        // properties
        public int Valx {get; set;}
        public int Valy {get; set;}
        public Hello()
        {
            Valx = 10; Valy = 20;
        }
        public int Sum(int x, int y)
        {
            Valx = x; Valy = y;
            return (Valx + Valy);
        }
    }
    public class RefTest
    {
        static void DelegateTest()
        {
            Hello h = new Hello();
            Type type = h.GetType();
            MethodInfo m = type.GetMethod("Sum");

            // Wrong! Delegate call = Delegate.CreateDelegate(type, m);
            Delegate call = Delegate.CreateDelegate(typeof(Func<int, int, int>), h, m);
            int res = (int) call.DynamicInvoke(new object[] {100, 200});
            Console.WriteLine("{0}", res);
            // This is a direct method implementation from Jon's post, and this is much faster
            Func<int, int, int> sum = (Func<int, int, int>) Delegate.CreateDelegate(typeof(Func<int, int, int>), h, m);
            res = sum(100, 200);
            Console.WriteLine("{0}", res);
        }
        static void Main()
        {
            DelegateTest();
        }
    }
}

添加2

根据 Jon 的回答,我做了一些性能测试以使用 sum 1000 时间。 与使用(int) call.DynamicInvoke(new object[] {100, 200});的方法相比,Func&lt;int, int, int&gt; sum = (Func&lt;int, int, int&gt;) Delegate.CreateDelegate(typeof(Func&lt;int, int, int&gt;), h, m);的速度快了300倍。

【问题讨论】:

    标签: c# .net reflection delegates


    【解决方案1】:

    Hello 不是委托类型 - 因此您不能将其作为第一个参数传递给 Delegate.CreateDelegate。您需要一个具有相同参数类型和返回类型的委托类型 - 在这种情况下,类似于:

    delegate int Foo(int x, int y);
    

    Func<int, int, int>
    

    还请注意,您调用的 Delegate.CreateDelegate 的重载旨在用于 static 方法 - 您应该使用也采用委托目标的重载(在本例,h)。

    我有一个blog post,它显示使用Delegate.CreateDelegate 来加快访问速度。请注意,我不希望DynamicInvoke 比直接使用反射调用方法快得多......它仍然需要检查参数类型等。真的你想要一个静态调用的强类型委托类型(相反动态)以使事情变得非常快。

    【讨论】:

      【解决方案2】:

      需要指定delegate的类型并绑定this参数。

      Delegate call = Delegate.CreateDelegate(typeof(Func<int, int, int>), h, m);
      

      【讨论】:

        【解决方案3】:

        你也可以使用:

        m.Invoke(null, new object[] { 100, 200 });
        

        它不会导致我一直在处理的任何性能问题。

        【讨论】:

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