Пример: ускорение API отражения с делегатом в .NET / C # - PullRequest
5 голосов
/ 21 июня 2011

Как спрашивается в этом посте , я придумал пример, который использует Delegate для ускорения Refect в .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();
        }
    }
}

ADDED2

Основываясь на ответе Джона, я провел тест производительности, чтобы использовать сумму 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 раз.

Ответы [ 3 ]

8 голосов
/ 21 июня 2011

Hello не является типом делегата - поэтому вы не можете передать его в Delegate.CreateDelegate в качестве первого аргумента. Вам нужен тип делегата с теми же типами параметров и типом возврата - в этом случае что-то вроде:

delegate int Foo(int x, int y);

или

Func<int, int, int>

Также обратите внимание, что вызванная вами перегрузка Delegate.CreateDelegate предназначена для использования статического метода - вам следует использовать перегрузку, которая также принимает цель делегата (в этом кейс, h).

У меня есть сообщение в блоге , которое показывает использование Delegate.CreateDelegate для ускорения доступа. Обратите внимание, что я не ожидал бы, что DynamicInvoke будет значительно быстрее, чем прямой вызов метода с отражением ... все равно придется проверять типы параметров и т. Д. На самом деле вам нужен строго типизированный тип делегата, вызываемый статически (в отличие от динамически) чтобы все было очень быстро.

2 голосов
/ 21 июня 2011

Вам необходимо указать тип делегата и связать параметр this.

Delegate call = Delegate.CreateDelegate(typeof(Func<int, int, int>), h, m);
0 голосов
/ 01 марта 2014

Вы также могли бы использовать:

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

Это не вызывает проблем с производительностью из того, с чем я имел дело.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...