示例:使用.NET/C#中的委托加速反射API

本文关键字:加速 反射 API 使用 NET 示例 | 更新日期: 2023-09-27 17:59:44

正如这篇文章中所问的,我提出了一个在.NET/C#.中使用Delegate来加速Refect的例子

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

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<int, int, int> sum = (Func<int, int, int>) Delegate.CreateDelegate(typeof(Func<int, int, int>), h, m);的速度快了300倍。

示例:使用.NET/C#中的委托加速反射API

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

delegate int Foo(int x, int y);

Func<int, int, int>

还要注意,您调用的Delegate.CreateDelegate的重载用于静态方法-您应该使用重载,该重载也接受委托的目标(在本例中为h)。

我有一篇博客文章,展示了使用Delegate.CreateDelegate来加快访问速度。请注意,我不希望DynamicInvoke比直接用反射调用方法快得多。。。它仍然需要检查参数类型等。实际上,你想要一个静态(而不是动态)的强类型委托类型,以使事情变得非常快。

您需要指定委托的类型并绑定this参数。

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

您也可以使用:

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

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