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

    使用传统的.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
        
    {
            
    public delegate object FastInvokeHandler(object target, object[] paramters);

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


            
    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++)
                
    {
                    
    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;
            }


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

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

            }


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

            }


            
    private static void EmitFastInt(ILGenerator il, int value)
            
    {
                
    switch (value)
                
    {
                    
    case -1:
                        il.Emit(OpCodes.Ldc_I4_M1);
                        
    return;
                    
    case 0:
                        il.Emit(OpCodes.Ldc_I4_0);
                        
    return;
                    
    case 1:
                        il.Emit(OpCodes.Ldc_I4_1);
                        
    return;
                    
    case 2:
                        il.Emit(OpCodes.Ldc_I4_2);
                        
    return;
                    
    case 3:
                        il.Emit(OpCodes.Ldc_I4_3);
                        
    return;
                    
    case 4:
                        il.Emit(OpCodes.Ldc_I4_4);
                        
    return;
                    
    case 5:
                        il.Emit(OpCodes.Ldc_I4_5);
                        
    return;
                    
    case 6:
                        il.Emit(OpCodes.Ldc_I4_6);
                        
    return;
                    
    case 7:
                        il.Emit(OpCodes.Ldc_I4_7);
                        
    return;
                    
    case 8:
                        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
        
    {
            
    static void Main(string[] args)
            
    {

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

                
    传统方式反射

                
    快速反射

                
    直接调用
                
                Console.ReadLine();
            }

        }


        
    public class Person
        
    {
            
    public void Say(ref string word, out Person p, int avi)
            
    {
                word 
    = "ttt" + avi.ToString();
                p 
    = new Person();

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

        }

    }

    原文:http://www.cnblogs.com/heekui/archive/2007/01/10/616654.html

    alarm   作者:NewSea     出处:http://newsea.cnblogs.com/    QQ,MSN:iamnewsea@hotmail.com

      如无特别标记说明,均为NewSea原创,版权私有,翻载必纠。欢迎交流,转载,但要在页面明显位置给出原文连接。谢谢。
  • 相关阅读:
    SpringMVC @PathVariable注解
    Spring REST
    SpringMVC @RequestMapping注解详解
    SpringMVC入门示例
    分布式系统中的幂等性
    常见性能优化策略的总结
    算法(Algorithms)第4版 练习 2.2.5
    算法(Algorithms)第4版 练习 2.2.23
    算法(Algorithms)第4版 练习 2.2.11(最终)
    算法(Algorithms)第4版 练习 2.2.11(3)
  • 原文地址:https://www.cnblogs.com/newsea/p/1707308.html
Copyright © 2011-2022 走看看