Click here to Skip to main content
Click here to Skip to main content

A General Fast Method Invoker

, 4 Jul 2006
Rate this:
Please Sign up or sign in to vote.
Method reflecting invoke is nice, but very frequently it can be too slow. This article describes an alternative method for dynamic method invoke.

Sample Image - FastMethodInvoker.gif

Introduction

Sometimes, I run across the need to dynamically invoke the method of an object, where the actual method might not be known until run-time. Usually, Reflecting is nice, but frequently doing it can be too slow. This article describes an alternative method for dynamic method invocation.

Background

When I read the article Fast Dynamic Property Accessors, I was thinking about my project, it has a lots of reflecting methods in circle. But it's methods not properties. But the DynamicMethod reminded me, maybe I could use Emit to generate a DynamicMethod to bind a special method before it can be invoked. I hope it will improve performance.

Using the Code

First, I reflected out the method which will be invoked:

MethodInfo methodInfo = typeof(Person).GetMethod("Say");

Then, I get the MethodInvoker to invoke:

FastInvokeHandler fastInvoker = GetMethodInvoker(methodInfo);
fastInvoker(new Person(), new object[]{"hello"});

Instead of using reflection method, invoke in the past:

methodInfo.Invoke(new Person(), new object[]{"hello"});

Implementation

First, I need to define a delegate to adapt the dynamic method:

public delegate object FastInvokeHandler(object target, 
                                   object[] paramters);

It looks the same as the class MethodInfo's Invoke method. Yes, that means I can write the same code to use it like in the past.

This code generates the DynamicMethod:

public static FastInvokeHandler GetMethodInvoker(MethodInfo methodInfo)
{
    DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, 
                     typeof(object), new Type[] { typeof(object), 
                     typeof(object[]) }, 
                     methodInfo.DeclaringType.Module);
    ILGenerator il = dynamicMethod.GetILGenerator();
    ParameterInfo[] ps = methodInfo.GetParameters();
    Type[] paramTypes = new Type[ps.Length];
    for (int i = 0; i < paramTypes.Length; i++)
    {
        paramTypes[i] = ps[i].ParameterType;
    }
    LocalBuilder[] locals = new LocalBuilder[paramTypes.Length];
    for (int i = 0; i < paramTypes.Length; i++)
    {
        locals[i] = il.DeclareLocal(paramTypes[i]);
    }
    for (int i = 0; i < paramTypes.Length; i++)
    {
        il.Emit(OpCodes.Ldarg_1);
        EmitFastInt(il, i);
        il.Emit(OpCodes.Ldelem_Ref);
        EmitCastToReference(il, paramTypes[i]);
        il.Emit(OpCodes.Stloc, locals[i]);
    }
    il.Emit(OpCodes.Ldarg_0);
    for (int i = 0; i < paramTypes.Length; i++)
    {
        il.Emit(OpCodes.Ldloc, locals[i]);
    }
    il.EmitCall(OpCodes.Call, methodInfo, null);
    if (methodInfo.ReturnType == typeof(void))
        il.Emit(OpCodes.Ldnull);
    else
        EmitBoxIfNeeded(il, methodInfo.ReturnType);
    il.Emit(OpCodes.Ret);
    FastInvokeHandler invoder = 
      (FastInvokeHandler)dynamicMethod.CreateDelegate(
      typeof(FastInvokeHandler));
    return invoder;
}

Conclusion

Well, I think this is a general way that can be used instead of most of the reflection methods to get about 50 times performance improvement. Any suggestions for improvements are welcome.

Extra advantage (reminded by MaxGuernsey): If an exception occurs in your code, FastInovker would throw the original one, but the Method.Invoke would throw a TargetInvocationException.

History

  • 2006-7-05: Updated to add static method support. Thanks Manuel Abadia.
  • 2006-6-30: Updated to add ref/out parameter support. Thanks Roger for his nice suggestion.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Luyan

China China
I am currently working for a .NET framework names AgileFramework. It's introduction at here:
http://www.agilelabs.cn/agileframework
 
Now I'm living in China. I have been designing and developing .NET based software applications for 5+ years.

Comments and Discussions

 
QuestionNot necessay at all PinmemberFatCatProgrammer22-Jan-13 8:25 
AnswerRe: Not necessay at all PinmemberLu Jing9-Jun-13 20:06 
AnswerRe: Not necessay at all Pinmembercajoncillos1-Jul-14 12:24 
GeneralRe: Not necessay at all PinmemberFatCatProgrammer1-Jul-14 16:10 
Questionabout your code's license Pinmemberqsmy12322-Aug-12 15:00 
QuestionLicense PinmemberSkeletor2323-Mar-12 5:05 
QuestionConstructorInfo Support. PinmemberMember 455125623-Jun-10 7:29 
I need something just like a fast method invoker, but instead of method invocation, i need to create instances of a runtimetype really fast.
 
Any ideas how to implement this?
 
public delegate object FastConstructorHandler(object[] paramters);
 
FastConstructorHandler GetConstructorInvoker(ConstructorInfo constructorInfo)
{
....
}
AnswerRe: ConstructorInfo Support. PinmemberMember 455125623-Jun-10 9:00 
QuestionCan't work with 'struct' ? Pinmemberqmxle1-Oct-09 5:11 
GeneralExcellent! Accessibility fix possible. Pinmemberblack198122-Jul-09 2:49 
QuestionPartial Trust question PinmemberAndrey Belykh25-Apr-08 6:57 
Generalprivate member supported and easier way with better performance Pinmemberyzh_x1-Jul-07 19:38 
GeneralRe: private member supported and easier way with better performance PinmemberLinguar2-Jul-07 9:15 
GeneralRe: private member supported and easier way with better performance Pinmemberyzh_x2-Jul-07 16:44 
GeneralRe: private member supported and easier way with better performance PinmemberLinguar2-Jul-07 18:26 
GeneralWrapper PinmemberMick O'Neill7-Jun-07 13:46 
GeneralRe: Wrapper Pinmemberjohnnycrash9917-May-09 9:03 
GeneralComments and structure. PinmemberLinguar19-Mar-07 6:56 
GeneralRe: Comments and structure. PinmemberLuyan24-Mar-07 2:35 
GeneralA Wrapper class for your code Pinmemberbilly p6-Oct-06 9:35 
GeneralI think the result is not exact Pinmemberhappyhippyie3-Sep-06 0:10 
GeneralRe: I think the result is not exact Pinmemberueqt20071-Sep-07 19:42 
AnswerRe: I think the result is not exact Pinmemberxx91819-Jan-08 3:29 
QuestionMethodAccessException unhandled when using generic string types Pinmembercanerten9-Aug-06 2:20 
QuestionRe: MethodAccessException unhandled when using generic string types Pinmembercanerten9-Aug-06 2:47 
Questionany suggestion about 1.1 Pinmemberaibo8-Aug-06 0:46 
QuestionSpeed Difference ? PinmemberGreg Roberts25-Jul-06 22:18 
AnswerRe: Speed Difference ? PinmemberLinguar19-Mar-07 13:23 
GeneralRe: Speed Difference ? Pinmemberwildcatsoft14-Aug-08 20:48 
GeneralRe: Speed Difference ? Pinmembercolinmeier2-Mar-11 10:00 
GeneralRe: Speed Difference ? PinmemberKerem Guemruekcue5-Dec-12 7:21 
GeneralNice Pinmembermikeperetz20-Jul-06 17:36 
QuestionHow do you "invoke in the past"? Pinmemberzxcv123412341234123420-Jul-06 4:13 
QuestionNewbie to Reflection Pinmembershahp11-Jul-06 6:38 
AnswerRe: Newbie to Reflection PinmemberLuyan11-Jul-06 22:31 
QuestionHow about private member call? Pinmembergattazzo19745-Jul-06 1:17 
AnswerRe: How about private member call? PinmemberStephen Erisman5-Jul-06 4:51 
GeneralRe: How about private member call? Pinmembergattazzo19745-Jul-06 6:25 
GeneralRe: How about private member call? PinmemberRoger J5-Jul-06 20:41 
GeneralRe: How about private member call? Pinmembergattazzo19746-Jul-06 7:16 
QuestionInteresting Pinmembermgungora4-Jul-06 9:21 
QuestionSource code use PinmemberManuel Abadia4-Jul-06 1:20 
AnswerRe: Source code use [modified] PinmemberLuyan4-Jul-06 2:19 
QuestionRe: Source code use [modified] PinmemberManuel Abadia4-Jul-06 6:00 
AnswerRe: Source code use PinmemberLuyan5-Jul-06 4:48 
GeneralAgreed. Five out of five. PinmemberMaxGuernsey3-Jul-06 18:27 
GeneralRe: Agreed. Five out of five. PinmemberLuyan3-Jul-06 22:44 
GeneralA Better Method PinmemberStephen Erisman3-Jul-06 18:10 
GeneralRe: A Better Method [modified] PinmemberLuyan3-Jul-06 22:34 
QuestionRe: A Better Method PinmemberStephen Erisman5-Jul-06 5:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.141022.2 | Last Updated 4 Jul 2006
Article Copyright 2006 by Luyan
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid