5,427,303 members and growing! (15,398 online)
Email Password   helpLost your password?
Languages » C# » General     Advanced

A General Fast Method Invoker

By Luyan

Method reflecting invoke is nice, but very frequently it can be too slow. This article describes an alternative method for dynamic method invoke.
C#, Windows, .NET, Visual Studio, Dev

Posted: 27 Jun 2006
Updated: 4 Jul 2006
Views: 56,485
Bookmarked: 117 times
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
63 votes for this Article.
Popularity: 8.70 Rating: 4.83 out of 5
2 votes, 3.2%
1
0 votes, 0.0%
2
1 vote, 1.6%
3
4 votes, 6.3%
4
56 votes, 88.9%
5

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

About the Author

Luyan


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.
Location: China China

Other popular C# articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 25 of 61 (Total in Forum: 61) (Refresh)FirstPrevNext
Subject  Author Date 
QuestionPartial Trust questionmemberAndrey Belykh7:57 25 Apr '08  
Generalprivate member supported and easier way with better performancememberyzh_x20:38 1 Jul '07  
GeneralRe: private member supported and easier way with better performancememberLinguar10:15 2 Jul '07  
GeneralRe: private member supported and easier way with better performancememberyzh_x17:44 2 Jul '07  
GeneralRe: private member supported and easier way with better performancememberLinguar19:26 2 Jul '07  
GeneralWrappermemberMick O'Neill14:46 7 Jun '07  
GeneralComments and structure.memberLinguar7:56 19 Mar '07  
GeneralRe: Comments and structure.memberLuyan3:35 24 Mar '07  
GeneralA Wrapper class for your codememberbilly p10:35 6 Oct '06  
GeneralI think the result is not exactmemberhappyhippyie1:10 3 Sep '06  
GeneralRe: I think the result is not exactmemberueqt200720:42 1 Sep '07  
AnswerRe: I think the result is not exactmemberxx9184:29 19 Jan '08  
QuestionMethodAccessException unhandled when using generic string typesmembercanerten3:20 9 Aug '06  
QuestionRe: MethodAccessException unhandled when using generic string typesmembercanerten3:47 9 Aug '06  
Questionany suggestion about 1.1memberaibo1:46 8 Aug '06  
GeneralSpeed Difference ?memberGreg Roberts23:18 25 Jul '06  
GeneralRe: Speed Difference ?memberLinguar14:23 19 Mar '07  
GeneralRe: Speed Difference ?memberwildcatsoft21:48 14 Aug '08  
GeneralNicemembermikeperetz18:36 20 Jul '06  
GeneralHow do you "invoke in the past"?memberzxcv12341234123412345:13 20 Jul '06  
QuestionNewbie to Reflectionmembershahp7:38 11 Jul '06  
AnswerRe: Newbie to ReflectionmemberLuyan23:31 11 Jul '06  
NewsHow about private member call?membergattazzo19742:17 5 Jul '06  
AnswerRe: How about private member call?memberStephen Erisman5:51 5 Jul '06  
GeneralRe: How about private member call?membergattazzo19747:25 5 Jul '06  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 4 Jul 2006
Editor: Smitha Vijayan
Copyright 2006 by Luyan
Everything else Copyright © CodeProject, 1999-2008
Web15 | Advertise on the Code Project