zoukankan      html  css  js  c++  java
  • (转)A General Fast Method Invoker

    (http://www.cnblogs.com/kidon/archive/2006/09/06/495936.aspx)

    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.

     程序下载

  • 相关阅读:
    PowerDesigner 15 之Check Model报错信息详解
    js出现:类不支持Automation操作
    IIS错误解决整理
    JavaScript页面跳转的几种方法
    JavaScript刷新上一级页面
    SQL 截断字符串查询(CharIndex()函数)
    JS 判断CHECKBOX复选框多选及选中项验证
    SQL 分组后返回序号(ROW_NUMBER () OVER(PARTITION BY order_no ORDER BY START_Time ASC 的使用方法)
    jquery 获取父窗口的元素 父窗口 子窗口[资料来源于网络]
    SQL Case When Then Else End的使用收集
  • 原文地址:https://www.cnblogs.com/cpcpc/p/2457073.html
Copyright © 2011-2022 走看看