Moin,
ich hab mir mal die ganzen Post zu Reflection angesehen, darunter auch ein Blogpost, der zeigen sollte, wie man aus einem Objekt MethodInfo einen delegatentypen erhalten kann, wenn der Typ nicht bekannt ist. Die Ansätze in allen Ehren, aber meine Tests mit diesem Quellcode
using System;
using System.Reflection;
using System.Text;
using System.Diagnostics;
public class Test
{
public delegate W Func<T, V, W>(T arg, V val);
public delegate int IndexOFDelegate(char c);
static void Main()
{
MethodInfo indexOf = typeof(string).GetMethod("IndexOf", new Type[] { typeof(char) });
IndexOFDelegate indexOfDelegate = (IndexOFDelegate)Delegate.CreateDelegate(typeof(IndexOFDelegate), "Hallo" ,typeof(string).GetMethod("IndexOf", new Type[] { typeof(char) }));
MethodInfo getByteCount = typeof(Encoding).GetMethod("GetByteCount", new Type[] { typeof(string) });
Func<string, object, object> indexOfFunc = MagicMethod<string>(indexOf);
Func<Encoding, object, object> getByteCountFunc = MagicMethod<Encoding>(getByteCount);
Stopwatch sw = new Stopwatch();
sw.Start();
indexOf.Invoke("Hello", new object[] { 'e' });
sw.Stop();
Console.WriteLine("Invoked MethodInfo " + sw.Elapsed.TotalMilliseconds.ToString());
sw.Reset();
sw.Start();
indexOfFunc("Hello", 'e');
sw.Stop();
Console.WriteLine("Created Delegate " + sw.Elapsed.TotalMilliseconds.ToString());
sw.Reset();
sw.Start();
indexOfDelegate('e');
sw.Stop();
Console.WriteLine("Declared Delegate " + sw.Elapsed.TotalMilliseconds.ToString());
Console.ReadKey();
}
static Func<T, object, object> MagicMethod<T>(MethodInfo method) where T : class
{
// First fetch the generic form
MethodInfo genericHelper = typeof(Test).GetMethod("MagicMethodHelper",
BindingFlags.Static | BindingFlags.NonPublic);
// Now supply the type arguments
MethodInfo constructedHelper = genericHelper.MakeGenericMethod
(typeof(T), method.GetParameters()[0].ParameterType, method.ReturnType);
// Now call it. The null argument is because it's a static method.
object ret = constructedHelper.Invoke(null, new object[] { method });
// Cast the result to the right kind of delegate and return it
return (Func<T, object, object>)ret;
}
static Func<TTarget, object, object> MagicMethodHelper<TTarget, TParam, TReturn>(MethodInfo method)
where TTarget : class
{
// Convert the slow MethodInfo into a fast, strongly typed, open delegate
Func<TTarget, TParam, TReturn> func = (Func<TTarget, TParam, TReturn>)Delegate.CreateDelegate
(typeof(Func<TTarget, TParam, TReturn>), method);
// Now create a more weakly typed delegate which will call the strongly typed one
Func<TTarget, object, object> ret = delegate(TTarget target, object param) { return func(target, (TParam)param); };
return ret;
}
}
haben angehängtes Ergebnis auf einer 32b XP-Maschine unter 2.0 geliefert, wobei ich mich dann doch fragen muss, was sich die ganzen Programmierer über die schlechte Performance von MethodInfo.Invoke() beschweren.
Gibt es denn noch irgendeine andere Möglichkeit unter 2.0 zur Laufzeit einen delegaten aus einem MethodInfo-Objekt zu erzeugen, dass an die Geschwindigkeit eines zur Buildzeit definierten delegaten herankommt?
EDIT: Eventuell indem man einen Methodenpointer in einen delegaten castet?