Background
I’ve recently been doing some optimisation work which has proved quite interesting in terms of working with reflection. My efforts porting Google’s Protocol Buffers are now pretty complete in terms of functionality, so I’ve been looking at improving the performance. The basic idea is that you specify your data types in a .proto file, and then generate C# from that. The generated C# allows you to manipulate the data, and serialize/deserialize it. When you generate the code, it can be optimised either for size or speed. The “small” code can end up being much smaller than the “fast” code – but it’s also significantly slower as it uses reflection when serializing and deserializing. My first rough-and-ready benchmark results (using a 130K data file based on Northwind) were slightly terrifying:
Operation | Time (ms) |
---|---|
Deserialize (fast) | 5.18 |
Serialize (fast) | 3.96 |
Deserialize (slow) | 429.49 |
Serialize (slow) | 103.67 |
Far from all of this difference was due to reflection, but it was a significant chunk – and provided the most interesting and challenging optimisation. This post doesn’t show the actual Protocol Buffer code, but demonstrates the three steps I required to radically improve the performance of reflection. The examples I’ve used are chosen just for simplicity.
Converting MethodInfo into a delegate instance
There are lots of things you can do with reflection, obviously – but I’m primarily interested in calling methods, using the associated MethodInfo
. This includes setting properties, using the results of the GetGetMethod
and GetSetMethod
methods of PropertyInfo
. We’ll use String.IndexOf(char)
as our initial example.
Normally when you’re calling methods with reflection, you call MethodInfo.Invoke
. Unfortunately, this proves to be quite slow. If you know the signature of the method at compile-time, you can convert the method into a delegate with that signature using Delegate.CreateDelegate(Type, object, MethodInfo)
. You simply pass in the delegate type you want to create an instance of, the target of the call (i.e. what the method will be called
on), and the method you want to call. It would be nice if there were a generic version of this call to avoid casting the result, but never mind. Here’s a complete example demonstrating how it works:
using System; using System.Reflection; public class Test { static void Main() { MethodInfo method = typeof(string).GetMethod("IndexOf", new Type[] { typeof(char) }); Func<char, int> converted = (Func<char, int>) Delegate.CreateDelegate(typeof(Func<char, int>), "Hello", method); Console.WriteLine(converted('l')); Console.WriteLine(converted('o')); Console.WriteLine(converted('x')); } }
This prints out 2, 4, and -1; exactly what we’d get if we’d called "Hello".IndexOf(...)
directly. Now let’s see what the speed differences are…
We’re mostly interested in the time taken to go from the main calling code to the method being called, whether that’s with a direct method call, MethodInfo.Invoke
or the delegate. To make IndexOf
itself take as little time as possible, I tested it by passing in ‘H’ so it would return 0 immediately. As normal, the test was rough and ready, but here are the results:
Invocation type | Stopwatch ticks per invocation |
---|---|
Direct | 0.18 |
Reflection | 120 |
Delegate | 0.20 |
One important point is that I created a new parameter array for each invocation of the MethodInfo
– obviously this is slightly costly in itself, but it mirrors real world usage. The exact numbers don’t matter, but the relative sizes are the important point: using a delegate invocation is only about 10% slower than direct invocation, whereas using reflection takes over 600 times as long. Of course these figures will depend on the method being called – if the direct invocation can be inlined, I’d expect that to make a significant difference in some cases. However, the benefit in converting reflection calls into delegate calls is obvious.
Now, what about if we wanted to vary the string we were calling IndexOf
on?
Interlude: open and closed delegates
When you create a delegate directly in C# using a method group conversion, you (almost) always create an open delegate for static methods and a closed delegate for instance methods. To explain the difference between open and closed delegates, it’s best to start thinking of all methods as being static – but with instance methods having an extra parameter at the start to represent this
. In fact, extension methods use exactly this model. Reality is more complicated than that due to polymorphism, but we’ll leave that to one side for the moment.
Going back to our String.IndexOf
example, we can start thinking of the signature as being:
static int IndexOf(string target, char c)
At this point it’s easy to explain the difference between open and closed delegates: a closed delegate has a value which it implicitly passes in as the first argument, whereas with an open delegate you specify all the arguments when you invoke the delegate. The implicit first argument is represented by the Delegate.Target
property. It’s null for open delegates – which is usually the case when you create a delegate directly in C#. Here’s a short program to demonstrate the difference when you create delegate instances using C# directly:
using System; public class Test { readonly string name; public Test(string name) { this.name = name; } public void Display() { Console.WriteLine("Test; name = {0}", name); } static void StaticMethod() { Console.WriteLine("Static method"); } static void Main() { Test foo = new Test("foo"); Action closed = foo.Display; // closed.Target == foo Action open = StaticMethod; // open.Target == null closed(); open(); } }
Before we go back to reflection, I’ll clarify the “almost” I used earlier on. You can’t currently create an open delegate referring to an instance method in C# using method group conversions – but you can create a closed delegate referring to a static method, if it’s an extension method. This makes sense, as extension methods are a strange sort of half-way house between static methods and instance methods – they’re truly static methods which can be used as if they were instance methods. I’ve got an example on my C# in Depth site.
Creating open delegates with reflection
Even though C# doesn’t support all the possible combinations of static/instance methods and open/closed delegates directly, Delegate.CreateDelegate
has overloads to let you do just that. The signature we used earlier (with parameters Type, object, MethodInfo
) always creates a closed delegate. There’s another overload without the middle parameter – and that always creates an open delegate. We can easily modify our earlier example to let us call String.IndexOf(char)
varying both the needle and the haystack, so to speak:
using System; using System.Reflection; public class Test { static void Main() { MethodInfo method = typeof(string).GetMethod("IndexOf", new Type[] { typeof(char) }); Func<string, char, int> converted = (Func<string, char, int>) Delegate.CreateDelegate(typeof(Func<string, char, int>), method); Console.WriteLine(converted("Hello", 'l')); Console.WriteLine(converted("Jon", 'o')); Console.WriteLine(converted("Hello", 'n')); } }
This prints 2, 1, -1, as if we’d called "Hello".IndexOf('l')
, "Jon".IndexOf('o')
and "Hello".IndexOf('n')
.
This can be a very powerful tool – in particular it’s crucial for my Protocol Buffers port: for a particular type, I can create a delegate which will set a property. I can keep that information around forever, and use the same delegate to set the property to different values on different instances of the type.
There’s just one more problem to overcome – and unfortunately this is where things get a little weird.
Adapting delegates for parameter and return types
Due to the way that the Protocol Buffer library works, I often need to call methods or set properties without knowing at compile-time what the parameter types are, or indeed the return type of the method. I can be confident that I’ll always call it with appropriate parameters, but I just don’t know what they’ll be ahead of time. Things are slightly better in terms of the type declaring the method – I know that at compile-time, although only as a generic type parameter. What I do know with confidence is the number of parameters (I’ll just specify a single parameter for our example), and whether or not the method will return a value (we’ll use an example which always returns a parameter).
What I need is a generic method which has a type parameter T
representing the type which implements the method, and which returns a Func
– a delegate instance which lets me pass the target and the argument value, and which will call the method and then return the value in a weakly typed manner. So we’d like this kind of program to work:
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) { // TODO: Implement this method! throw new NotImplementedException(); } }
Note: I was going to demonstrate this by calling DateTime.AddDays
, but for value type instance methods the implicit first first parameter is passed by reference, so we’d need a delegate type with a signature of DateTime Foo(ref DateTime original, double days)
to call CreateDelegate
. It’s feasible, but a bit of a faff. In particular, you can’t use Func
as that doesn’t have any
by-reference parameters.
Make sure you understand what we’re aiming for here. Notice that we’re not really type-safe – just like we wouldn’t be if we were calling MethodInfo.Invoke
. Of course we’d normally want type safety, but in this case it would make the calling code much more complicated, and in some places it might effectively be impossible. So, with the goal in place, we know we need to implement MagicMethod
. (It’s not called MagicMethod
in the real source code, of course – but frankly it’s quite a tricky method to name sensibly, and at this stage it really does feel like magic.)
The first obvious attempt at implementing MagicMethod
would be to use CreateDelegate
as we’ve done before, like this:
// Warning: doesn't actually work! static Func<T, object, object> MagicMethod<T>(MethodInfo method) { return (Func<T, object, object>) Delegate.CreateDelegate(typeof(Func<T, object, object>), method); }
Unfortunately, that fails – the call to CreateDelegate
fails with an ArgumentException
because the delegate type isn’t right for the method that we’re trying to call. The delegate types don’t have to be exactly right, just compatible (as of .NET 2.0) – but we need an explicit conversion from object
to the right parameter type, and a potentially boxing conversion of the return value. We still want to call CreateDelegate
though… so somewhere we’re going to have to create a Func
where TTarget
is a type parameter representing the type of object we’re going to call the method on, TParam
is the type of the single parameter the method accepts, and TReturn
is the return type of the method.
We could do that directly with reflection, using typeof(Func)
to get the open type (not to be confused with an open delegate!), then calling Type.MakeGenericType
to create the right constructed type. We’ll need to do something like that anyway, but it’s actually easier to write another generic method with the right type parameters for this part. That will let us convert the MethodInfo
into a delegate, but then what are we going to do with it? How can we convert a Func
into a Func
? Well, we need to cast the parameter from object
to TParam
, and then convert the result from TReturn
to object
, which may involve boxing. If we were writing a method to do this, it would look something like this:
static object CallAndConvert<TTarget, TParam, TReturn> (Func<TTarget, TParam, TReturn> func, TTarget target, object param) { // Conversion from TReturn to object is implicit return func(target, (TParam) param); }
We don’t want to execute that code at the moment – we want to create a delegate which will execute it later. The easiest way to do that is to move the code into a lambda expression within a normal method which already has a reference to the Func
. That lambda expression will then be converted into a delegate of the type we really want. It may feel like we’re just adding layer upon layer of indirection (and indeed we are) but we’re genuinely making progress. Honest. Here’s the new generic method:
static Func<TTarget, object, object> MagicMethodHelper<TTarget, TParam, TReturn>(MethodInfo method) { // 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; }
(We could return the lambda expression directly – the ret
variable is only present as an attempt to add some clarity.)
We’re now just one step away from having a working program – we need to implement MagicMethod
by calling MagicMethodHelper
. There’s one obvious problem though – we need three type arguments to call MagicMethodHelper
, and we’ve only got one of them in MagicMethod
. We know the other two at execution time, based on the parameter type and return type of the MethodInfo
we’ve been
passed. The fact that we only know them at execution time suggests the next step – we need to use reflection to invoke MagicMethodHelper
. We need to fetch the generic method and then supply the type arguments. It’s easier to show this than to describe it:
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; }
I’ve added the where T : class
constraint to make sure (at compile-time) that we don’t run into the problem I mentioned earlier around calling value type methods. It may seem slightly odd that we’re using reflection to call MagicMethodHelper
when the whole point of the exercise was to avoid invoking methods by reflection – but we only need to invoke the method once, and we can use the returned delegate many times. Here’s the complete program, ready to compile and run:
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; } }
Conclusion
This isn’t the kind of thing which I enjoy having in production code. It’s frightfully complicated – we’re finding a method via reflection, invoking a different (and generic) method via reflection in order to turn the first method into a delegate and then return a different delegate which calls it. While I don’t like having “clever” code like this in production, I take immense pleasure from getting it to work in the first place. This is one of the rare occasions where the result makes all the cleverness worth it, too – combined with the other optimisations, my Protocol Buffers port is now much, much faster – the reflection invocations are no longer a bottleneck. (We lose a little bit of efficiency by having one delegate call another, but it’s still massively quicker than using reflection.)
Regardless of the complexity involved later on, the simpler parts of this post (calling Delegate.CreateDelegate
where you already know the signature, and the possibility of creating open delegates) are likely to be more widely applicable. By using a delegate instead of MethodInfo
, not only are there significant performance improvements, but also a strongly typed way of calling the method. From now on, I’ll certainly be considering whether or not it might be worth using a delegate any time I use reflection.
Good write up; I use the same trick (especially the open delegate to call an instance method) quite frequently, but with an additional micro-optimisation; by making the *caller* generic, you can avoid the cast and (potentially) box/unbox. But this is nowhere as signifcant as the difference simply from using a typed delegate (rather than just Delegate or MethodInfo).
Unfortunately, having a generic caller adds another dimension and tend to involve yet more MakeGeneric[Method|Type]… but “every little helps” ;-p
LikeLiked by 1 person
Hi Jon,
A great article on optimization – it’s been a while since you’ve been writing on this topic.
While I agree that the complexity of this implementation is quite high, it’s important to realize that this pattern (and related implementations) is becoming more common these days – meaning that more developers would be able to step up to the task of maintaining and evolving the code.
The number of applications that can benefit from this is increasing rapidly; especially with APIs in e.g. content management applications that supports untyped lists / tables (think SharePoint and so on) where dynamic creation of fields (that are not know at compile time) requires a really fast implementation.
The performance of the untyped lists (and thus their overall benefit and succes) directly relates to the performance of the underlying API.
I’m not familiar with the implementation of the Protocol Buffers projects, but if there’s a requirement for calling a known method on a dynamic type, you could benefit from dynamic IL emission and cache the concrete delegate.
In the CMS API I’m working on, one of the requirements is to do just that; call a known method (in this case a constructor) on a dynamic type (a lot of examples like this is starting to show up these days – it’s almost like a trend). There’s a lot of performance in code like this, but you have to stay sharp and document every step thoroughly.
Here’s the part of the framework I was referring to above, namely the dynamic creation of CmsField instances (that goes into the x/y coordinate of a row/column) by means of creating a concrete delegate for each dynamic type encountered during runtime.
Because of optimizations like this, all types (not just internals) become first class citizens in terms of performance (100.000s per sec.) – I really like that way of thinking.
private static Dictionary _cache = new Dictionary();
private delegate CmsField FieldDelegate(CmsContext cms);
public static CmsField GetFieldDelegate(CmsContext cms, string typeName)
{
if (typeName == null) { throw new ArgumentNullException(“typeName”); }
FieldDelegate result = null;
if (_cache.TryGetValue(typeName, out result)) { return result(cms); }
lock (_cache)
{
if (_cache.TryGetValue(typeName, out result)) { return result(cms); }
Type type = Type.GetType(typeName);
if (type == null) { throw new InvalidOperationException(string.Format(“Unable to find the type ‘{0}’.”, typeName)); }
ConstructorInfo info = type.GetConstructor(new Type[] { typeof(CmsContext) });
if (info == null) { throw new InvalidOperationException(string.Format(“Unable to find a public constructor with the signature ‘{0}(CmsContext)’ for type {1}”, type.Name, typeName)); }
var method = new DynamicMethod(“”, typeof(CmsField), new Type[] { typeof(CmsContext) }, type);
ILGenerator il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Newobj, info);
il.Emit(OpCodes.Ret);
_cache.Add(typeName, result = (FieldDelegate) method.CreateDelegate(typeof(FieldDelegate)));
}
return result(cms);
}
I’m sure you’ve ventured down this path before, but it would be interesting to see your take on thoughts such as this (strictly related to performance).
LikeLike
Anders: I haven’t actually gone down the manual IL emission route yet, but I’ve certainly considered it. However, I wonder what the memory implications might be. In particular, part of the point of using “optimise for size” is to avoid creating too much code for the JITter etc. I have to admit that I don’t know what the memory implications of using even the technique I’ve got at the moment might be.
To be honest I would really suggest that for almost *all* situations “optimise for speed” is far more appropriate for Protocol Buffers. I don’t know why it’s not the default :(
At the moment the bottleneck isn’t in the reflection itself, so I probably won’t try IL emission in this particular case… but sooner or later I’m bound to want it :)
Jon
LikeLike
Hello Jon.
I think, that usage of Expressions can make solution move obvious and “expressive” :)
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(indexOf);
var getByteCountFunc = MagicMethod(getByteCount);
Console.WriteLine(indexOfFunc(“Hello”, ‘e’));
Console.WriteLine(getByteCountFunc(Encoding.UTF8, “Euro sign: u20ac”));
}
static Func MagicMethod(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>(
Expression.Convert(methodCall, typeof (object)),
instance, argument
).Compile();
}
LikeLike
Hi what is the ‘Func’ in static Func MagicMethod(MethodInfo method)
LikeLike
It’s the
System.Func<T1, T2, TResult>
delegate.LikeLike
Vladimir: Yes, expression trees can make this a lot simpler. Unfortunately I’m targeting .NET 2.0…
Jon
LikeLiked by 1 person
Nice writeup. An old MSDN article by Joel Pobar (CLR PM) found here: http://msdn.microsoft.com/en-us/magazine/cc163759.aspx talks about similar techniques, and also includes information about dynamically generating code through DynamicMethod to improve performance.
LikeLike
I’m got some code lying around where I created some strong-typed wrappers around the reflection types, to denote such things as declaring class, data type of property, etc.
It was an interesting exercise.
LikeLike
Hi Jon,
Great article… but I have a problem.
I ned to use this idea in .Net 2.0… as in I don’t have access to lambda expressions. (I was surpriced at your comment to Vladimir).
How would this be resolved without using lambda expressions?
LikeLike
@Varas: You just need to change the lambda expressions into anonymous methods. For instance change the lambda expression in the example into:
Func ret = delegate(TTarget target, object param)
{ return func(target, (TParam) param); };
Hope this helps,
Jon
LikeLike
GREAT!!!
Now it works. Here is the full example, including the Correction to the lamda and the declaration of Func:
using System;
using System.Reflection;
using System.Text;
public class Test {
public delegate W Func( T arg, V val );
static void Main( ) {
MethodInfo indexOf = typeof( string ).GetMethod( “IndexOf”, new Type[ ] { typeof( char ) } );
MethodInfo getByteCount = typeof( Encoding ).GetMethod( “GetByteCount”, new Type[ ] { typeof( string ) } );
Func indexOfFunc = MagicMethod( indexOf );
Func getByteCountFunc = MagicMethod( getByteCount );
Console.WriteLine( indexOfFunc( “Hello”, ‘e’ ) );
Console.WriteLine( getByteCountFunc( Encoding.UTF8, “Euro sign: u20ac” ) );
Console.ReadKey( );
}
static Func MagicMethod( 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 )ret;
}
static Func MagicMethodHelper( MethodInfo method )
where TTarget: class {
// Convert the slow MethodInfo into a fast, strongly typed, open delegate
Func func = ( Func )Delegate.CreateDelegate
( typeof( Func ), method );
// Now create a more weakly typed delegate which will call the strongly typed one
Func ret = delegate( TTarget target, object param ) { return func( target, ( TParam )param ); };
return ret;
}
}
LikeLiked by 1 person
well, this works as long as the parameters are not array. For example, using this method to call “teststring”.TrimEnd(new char[] {‘a’}) with give an error, saying cannot convert ‘System.Object[]’ to ‘System.Char[]’. Any cure for this?
LikeLike
@Kelvin: Could you say exactly what’s failing for you? It’s not clear what you’re trying to do, exactly.
Here’s the equivalent Main method calling MagicHelper (unchanged) for TrimEnd:
static void Main()
{
MethodInfo trimEnd = typeof(string).GetMethod(“TrimEnd”, new Type[]{typeof(char[])});
Func trimEndFunc = MagicMethod(trimEnd);
Console.WriteLine(trimEndFunc(“teststring”, new char[]{‘a’}));
Console.WriteLine(trimEndFunc(“teststring”, new char[]{‘n’, ‘g’}));
}
If you want to mail me (skeet@pobox.com) any failing code, that might work better than doing it here.
Jon
LikeLike
Jon, sorry it’s a bug on my side. I was testing a couple of reflection methods and passed (new object[]{new char[]{‘a’}}) to the delegate instead of (new char[]{‘a’}).
LikeLike
Even if you don’t care about performance, consider using delegate over MethodInfo.Invoke() because delegate does not wrap exceptions in
TargetInvocationException. Unwrapping exceptions from TargetInvocationException can be a real pain especially when you don’t want to loose the stacktrace (see http://stackoverflow.com/questions/57383/in-c-how-can-i-rethrow-innerexception-without-losing-stack-trace).
LikeLiked by 1 person
Jon
I recently came across this post while exploring a similar implementation.
Have released a multimethod dispatcher that utilizes this technique for invoking reflected methods.
http://www.codeplex.com/multimethods
Cheers
Ajai
LikeLike
Great post! found this when I was surprised by my own test result. You article confirm this for me.
In terms of the generic part, there are two different workarounds that you get return the strong typed delegate instead of general Delegate type. For detail see http://kennethxu.blogspot.com/2009/05/strong-typed-high-performance.html
I have created a library that provides extension methods so you can simply do this:
var indexOfFunc = typeof(string).GetInstanceInvoker<Func>(“IndexOf”);
int index = indexOfFunc(“Hello”, ‘e’);
Cheers!
LikeLike
Hi Jon – Really wonderful post !!
I think i am missing something and am not able to visualize statement you made :
“I often need to call methods or set properties without knowing at compile-time what the parameter types are, or indeed the return type of the method” and per below snippet, you able to create delegate having parameter and return type as object, but to get that you passing methodInfo (indexOf) which you created by knowing method parameter type at compile time.
Func<string, object, object> indexOfFunc = MagicMethod(indexOf);
Thanks!!
LikeLike
It’s not quite sure what you mean – the clearest way of trying this is to look at the final code. Have you tried that, and then experimented with changing it?
LikeLike
There is absolutely no problem with compiling and running code. But what i am not getting is how did it served the intention of calling a method when you don’t know the type of method parameter or type of return value at compile time – because in order to create delegate of that nature, you need to use methodInfo by defining the method parameter type at compile time.
OR is it expected that methodInfo will be decided and picked at run time (say via some factory pattern)
LikeLike
It’s expected that the MethodInfo is found in some other way, but exactly how or why is out of the scope of the blog post – there are various situations in which it can be useful. (Given that it’s nearly 10 years ago, I can’t remember any information that provided background to the post…)
LikeLike
https://github.com/jskeet/dotnet-protobufs/tree/master is now showing a 404.
I am quite keen to see how you used this for property setting during serialization/deserialization…
LikeLike
That port is now at https://github.com/jskeet/protobuf-csharp-port – I’ve edited the post. I suspect the relevant code is https://github.com/jskeet/protobuf-csharp-port/blob/master/src/ProtocolBuffers/FieldAccess/ReflectionUtil.cs
LikeLike
I cannot get the code to compile because the generic arguments to the functions seem to be missing. Are they being treated as HTML tags?
LikeLike
Which piece of code are you trying to compile? It may well be that some type arguments have been missed when I was escaping things.
LikeLike
The final grey box with all the code in it – for example, I see that MagicMethod has no T in angle brackets before (MethodInfo method) where T : class.
LikeLike
Okay, the whole post was busted – basically when I converted from one site to another ages ago. I’ve rewritten the whole thing in Markdown, and it should be okay now…
LikeLike
Many thanks Jon – far easier to study now!
LikeLike
Hi Jon thanks for this info.
I’ve been experimenting with just getting property values and it seems since dotnet core (at least v3) PropertyInfo.GetValue() is now plenty quick. Have you any insights into what optimisations they did and if it also applies more generally?
LikeLike
Hmm… it’s entirely possible that we just have different ideas of what’s quick enough… but I haven’t done any benchmarking to see the differences over time, I’m afraid.
LikeLike
I can easily get over 10 million GetValue()s per second on my laptop. Using your technique I get about 50% more, but given how little time a GetValue() now takes its going to get lost in the wash compared to everything else the system will be doing.
LikeLike