zoukankan      html  css  js  c++  java
  • 推荐一个快速反射调用的类

    本文转载:http://blog.csdn.net/jehnjehn/article/details/7086863

    使用传统的.net反射机制,调用类的方法时,在调用频率大的情况下,会感觉速度很慢。最近浏览卢彦的博客时,找到一个他改进后的反射调用类。试用以后感觉效率明显提高,特推荐给大家。作者重新实现了,反射调用方法,但是调用接口和.net原有方法一致。而且调用时抛出的异常为所调用类的实际异常,不像传统方式返回为包装异常。
    文章来源:
    http://www.codeproject.com/csharp/FastMethodInvoker.asp

    快速反射调用类

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Reflection;
    using System.Reflection.Emit;

    namespace FastMethodInvoker
    {
       
    class FastInvoke
       
    {
           
    publicdelegateobject FastInvokeHandler(object target, object[] paramters);

           
    staticobject InvokeMethod(FastInvokeHandler invoke, object target, paramsobject[] paramters)
           
    {
               
    return invoke(null, paramters);
            }


           
    publicstatic 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++)
               
    {
                   
    if (ps[i].ParameterType.IsByRef)
                        paramTypes[i]
    = ps[i].ParameterType.GetElementType();
                   
    else
                        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], true);
                }

               
    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]);
                }

               
    if (!methodInfo.IsStatic)
               
    {
                    il.Emit(OpCodes.Ldarg_0);
                }

               
    for (int i =0; i < paramTypes.Length; i++)
               
    {
                   
    if (ps[i].ParameterType.IsByRef)
                        il.Emit(OpCodes.Ldloca_S, locals[i]);
                   
    else
                        il.Emit(OpCodes.Ldloc, locals[i]);
                }

               
    if (methodInfo.IsStatic)
                    il.EmitCall(OpCodes.Call, methodInfo,
    null);
               
    else
                    il.EmitCall(OpCodes.Callvirt, methodInfo,
    null);
               
    if (methodInfo.ReturnType ==typeof(void))
                    il.Emit(OpCodes.Ldnull);
               
    else
                    EmitBoxIfNeeded(il, methodInfo.ReturnType);

               
    for (int i =0; i < paramTypes.Length; i++)
               
    {
                   
    if (ps[i].ParameterType.IsByRef)
                   
    {
                        il.Emit(OpCodes.Ldarg_1);
                        EmitFastInt(il, i);
                        il.Emit(OpCodes.Ldloc, locals[i]);
                       
    if (locals[i].LocalType.IsValueType)
                            il.Emit(OpCodes.Box, locals[i].LocalType);
                        il.Emit(OpCodes.Stelem_Ref);
                    }

                }


                il.Emit(OpCodes.Ret);
                FastInvokeHandler invoder
    = (FastInvokeHandler)dynamicMethod.CreateDelegate(typeof(FastInvokeHandler));
               
    return invoder;
            }


           
    privatestaticvoid EmitCastToReference(ILGenerator il, System.Type type)
           
    {
               
    if (type.IsValueType)
               
    {
                    il.Emit(OpCodes.Unbox_Any, type);
                }

               
    else
               
    {
                    il.Emit(OpCodes.Castclass, type);
                }

            }


           
    privatestaticvoid EmitBoxIfNeeded(ILGenerator il, System.Type type)
           
    {
               
    if (type.IsValueType)
               
    {
                    il.Emit(OpCodes.Box, type);
                }

            }


           
    privatestaticvoid EmitFastInt(ILGenerator il, int value)
           
    {
               
    switch (value)
               
    {
                   
    case-1:
                        il.Emit(OpCodes.Ldc_I4_M1);
                       
    return;
                   
    case0:
                        il.Emit(OpCodes.Ldc_I4_0);
                       
    return;
                   
    case1:
                        il.Emit(OpCodes.Ldc_I4_1);
                       
    return;
                   
    case2:
                        il.Emit(OpCodes.Ldc_I4_2);
                       
    return;
                   
    case3:
                        il.Emit(OpCodes.Ldc_I4_3);
                       
    return;
                   
    case4:
                        il.Emit(OpCodes.Ldc_I4_4);
                       
    return;
                   
    case5:
                        il.Emit(OpCodes.Ldc_I4_5);
                       
    return;
                   
    case6:
                        il.Emit(OpCodes.Ldc_I4_6);
                       
    return;
                   
    case7:
                        il.Emit(OpCodes.Ldc_I4_7);
                       
    return;
                   
    case8:
                        il.Emit(OpCodes.Ldc_I4_8);
                       
    return;
                }


               
    if (value >-129&& value <128)
               
    {
                    il.Emit(OpCodes.Ldc_I4_S, (SByte)value);
                }

               
    else
               
    {
                    il.Emit(OpCodes.Ldc_I4, value);
                }

            }

        }

    }


    效果测试程序

    using System;
    using System.Reflection;
    using System.Reflection.Emit;
    using System.Collections.Generic;
    using System.Text;
    using System.Diagnostics;

    namespace FastMethodInvoker
    {
       
    class Program
       
    {
           
    staticvoid Main(string[] args)
           
    {

                Type t
    =typeof(Person);
                MethodInfo methodInfo
    = t.GetMethod("Say");
                Person person
    =new Person();
               
    string word ="hello";
                Person p
    =null;
               
    object[] param =newobject[] { word, p, 3 };
               
    int TestTimes =100000; //测试次数,可自行调节看效果

               
    #region 传统方式反射
               
    try
               
    {
                    Stopwatch watch
    =new Stopwatch();
                    watch.Start();
                   
    for (int i =0; i < TestTimes; i++)
                   
    {
                        methodInfo.Invoke(person, param);
                    }

                    watch.Stop();
                    Console.WriteLine(TestTimes.ToString()
    +" times invoked by Reflection: "+ watch.ElapsedMilliseconds +"ms");
                }

               
    catch (System.Exception ex)
               
    {
                    Console.WriteLine(
    "传统方式反射 直接错误:"+ ex.Message);
                    Console.WriteLine(
    "传统方式反射 内部错误:"+ ex.InnerException.Message);
                }

               
    #endregion


               
    #region 快速反射
               
    try
               
    {
                    Stopwatch watch1
    =new Stopwatch();
                    FastInvoke.FastInvokeHandler fastInvoker
    = FastInvoke.GetMethodInvoker(methodInfo);
                    watch1.Start();
                   
    for (int i =0; i < TestTimes; i++)
                   
    {
                        fastInvoker(person, param);
                    }

                    watch1.Stop();
                    Console.WriteLine(TestTimes.ToString()
    +" times invoked by FastInvoke: "+ watch1.ElapsedMilliseconds +"ms");
                }

               
    catch (System.Exception ex)
               
    {
                    Console.WriteLine(
    "快速反射 错误:"+ ex.Message);
                }

               
    #endregion


               
    #region 直接调用
               
    try
               
    {
                    Stopwatch watch2
    =new Stopwatch();
                    watch2.Start();
                   
    for (int i =0; i < TestTimes; i++)
                   
    {
                        person.Say(
    ref word, out p, 3);
                    }

                    watch2.Stop();
                    Console.WriteLine(TestTimes.ToString()
    +" times invoked by DirectCall: "+ watch2.ElapsedMilliseconds +"ms");
                }

               
    catch (System.Exception ex)
               
    {
                    Console.WriteLine(
    "直接调用 错误:"+ ex.Message);
                }

               
    #endregion

               
                Console.ReadLine();
            }

        }


       
    publicclass Person
       
    {
           
    publicvoid Say(refstring word, out Person p, int avi)
           
    {
                word
    ="ttt"+ avi.ToString();
                p
    =new Person();

               
    //throw new System.Exception("出错了哦");
            }

        }

    }

  • 相关阅读:
    TCP的核心系列 — SACK和DSACK的实现(一)
    Linux2.6中的Slab层
    UVA 11549 Calculator Conundrum (Floyd判圈算法)
    2013第四届蓝桥杯决赛Java高职高专组题目以及解法答案
    hdu-Common Subsequence
    UVA 10869
    【Struts2学习笔记(3)】至Action注入属性值
    【winows7+android-ndk-r9+Cygwin 】cocos2dx 2.*游戏移植Android平台完全手册
    Ubuntu 14.04 64位字体美化(使用黑文泉驿)
    Android Fragment——详细解释
  • 原文地址:https://www.cnblogs.com/51net/p/2479822.html
Copyright © 2011-2022 走看看