As is asked in this post, I came up with an example that uses Delegate to speedup Refection in .NET/C#.
However, I got this error when running (compilation works fine). What might be wrong?
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
ADDED
This is the (working) source code thanks to the help from 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
Based on Jon's answer, I did some performance test to use sum 1000 time.
Compared to the method of using (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);
is 300 times faster.
You could have also used:
It doesn't cause any performance issues from what I've been dealing with.
You need to specify the type of delegate and bind the
this
parameter.Hello
isn't a delegate type - so you can't pass it intoDelegate.CreateDelegate
as the first argument. You need a delegate type with the same parameter types and return type - in this case, something like:or
Also note that the overload of
Delegate.CreateDelegate
you've called is meant to be used for a static method - you ought to be using the overload which also takes the target of the delegate (in this case,h
).I have a blog post which shows using
Delegate.CreateDelegate
for speeding up access. Note that I wouldn't expectDynamicInvoke
to be significantly faster than calling the method directly with reflection... it's still going to have to check the parameter types etc. Really you want a strongly-typed delegate type called statically (as opposed to dynamically) to make things really fast.