Revision: 24847
Updated Code
at March 12, 2010 10:16 by pckujawa
Updated Code
using System; using System.Reflection; using System.Text; public class Test { static void Main() { MethodInfo indexOf = 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); Console.WriteLine(indexOfFunc("Hello", 'e')); Console.WriteLine(getByteCountFunc(Encoding.UTF8, "Euro sign: \u20ac")); } 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 = (TTarget target, object param) => func(target, (TParam) param); return ret; } } // Or, for C# 3+ public static void Main(string[] args) { var indexOf = typeof(string).GetMethod("IndexOf", new[] { typeof(char) }); var getByteCount = typeof(Encoding).GetMethod("GetByteCount", new[] { typeof(string) }); var indexOfFunc = MagicMethod<string>(indexOf); var getByteCountFunc = MagicMethod<Encoding>(getByteCount); Console.WriteLine(indexOfFunc("Hello", 'e')); Console.WriteLine(getByteCountFunc(Encoding.UTF8, "Euro sign: \u20ac")); } static Func<T, object, object> MagicMethod<T>(MethodInfo method) { var parameter = method.GetParameters().Single(); var instance = Expression.Parameter(typeof (T), "instance"); var argument = Expression.Parameter(typeof (object), "argument"); var methodCall = Expression.Call( instance, method, Expression.Convert(argument, parameter.ParameterType) ); return Expression.Lambda<Func<T, object, object>>( Expression.Convert(methodCall, typeof (object)), instance, argument ).Compile(); }
Revision: 24846
Updated Code
at March 12, 2010 10:14 by pckujawa
Updated Code
using System; using System.Reflection; using System.Text; public class Test { static void Main() { MethodInfo indexOf = 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); Console.WriteLine(indexOfFunc("Hello", 'e')); Console.WriteLine(getByteCountFunc(Encoding.UTF8, "Euro sign: \u20ac")); } 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 = (TTarget target, object param) => func(target, (TParam) param); return ret; } }
Revision: 24845
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at March 12, 2010 10:13 by pckujawa
Initial Code
using System; using System.Reflection; using System.Text; public class Test { static void Main() { MethodInfo indexOf = 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); Console.WriteLine(indexOfFunc(\"Hello\", \'e\')); Console.WriteLine(getByteCountFunc(Encoding.UTF8, \"Euro sign: \\u20ac\")); } 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 = (TTarget target, object param) => func(target, (TParam) param); return ret; } }
Initial URL
http://msmvps.com/blogs/jon_skeet/archive/2008/08/09/making-reflection-fly-and-exploring-delegates.aspx
Initial Description
Initial Title
Converting MethodInfo into a delegate instance to improve performance
Initial Tags
Initial Language
C#