public 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; //测试次数,可自行调节看效果

            #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();
        }
    }

    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("出错了哦");
        }
    }
}

C# 快速反射 IL的更多相关文章

  1. [源码]Literacy 快速反射读写对象属性,字段

    Literacy 说明 Literacy使用IL指令生成方法委托,性能方面,在调用次数达到一定量的时候比反射高很多 当然,用IL指令生成一个方法也是有时间消耗的,所以在只使用一次或少数几次的情况,不但 ...

  2. 快速反射DataTable

    public class SetterWrapper<TTarget, TValue> { private Action<TTarget, TValue> _setter; p ...

  3. 在 .NET 平台使用 ReflectionDynamicObject 优化反射调用代码

    基于封装的原则,API 的设计者会将部分成员(属性.字段.方法等)隐藏以保证健壮性.但总有需要直接访问这些私有成员的情况. 为了访问一个类型的私有成员,除了更改 API 设计还有就是使用反射技术: p ...

  4. 更新Literacy

    之前都没有做单元测试的啊 昨天离职了,闲着没事做了个单元测试,结果发现一堆问题....大部分都是关于值类型在IL中的操作问题... 这件事让我感觉蛋蛋隐隐发疼....以后一定要做单元测试啊.... 具 ...

  5. 一种简单,轻量,灵活的C#对象转Json对象的方案(续)

    本文参考资料 一种简单,轻量,灵活的C#对象转Json对象的方案 [源码]Literacy 快速反射读写对象属性,字段 一段废话 之前我已经介绍了这个方案的名称为JsonBuilder,这套方案最大的 ...

  6. Java动态代理全面分析

    代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1  主题:规定代理类和真实对象共同对外暴露的接口: 2  代理类:专门代理真实对象的类: 3 ...

  7. Java动态代理与Cglib库

    JDK动态代理 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在 ...

  8. 解决你的开发烦恼——Aoite 开源前奏

    Aoite(Any one item!) 一个适于任何 .Net Framework 4.0+ 项目的快速开发整体解决方案,敬请关注 Aoite GitHub. 介绍 本项目从2009年孵化(V-&g ...

  9. 热更新脚本C#light,ulua,Scorpio性能比较

    http://www.unity蛮牛.com/thread-32861-1-1.html 测试环境: unity4.5.2  三个脚本全是源码导入  PC :处理器 Intel(R) Core(TM) ...

随机推荐

  1. 実行時にMicrosoft.ACE.OLEDB.12.0プロバイダーはローカルコンピュータに登録されていませんが出てしまう

    環境 Windows8 64bit Visual Studio 2010 Access 2010 32bit 接続プロバイダは「Microsoft.ACE.OLEDB.12.0」 対応 Downloa ...

  2. eclipse 启动后,闪退

    网上的大部分是说删除 .metadata    说会workspace里面项目会消失 下面这个可以启动,项目还在 最好解决办法: 删除文件 [workspace]/.metadata/.plugins ...

  3. schedule() 和 scheduleAtFixedRate() 区别

    1.  schedule() ,2个参数方法:在执行任务时,如果指定的计划执行时间scheduledExecutionTime <= systemCurrentTime,则task会被立即执行. ...

  4. C#、.NET网络请求总结(WebClient和WebRequest)

    1.关于WebClient第三方的封装,支持多文件上传等 using System; using System.Collections.Generic; using System.Text; usin ...

  5. jquery自定义类似$.ajax()的方法

    热腾腾的代码: <script type="text/javascript"> $.extend({ testgogo: function (options) { va ...

  6. 用SQL server导出到oracle,查询时提示“表或视图不存在ORA-00942”错误

    用SQL server2005的导出工具,将数据导出表到oracle,表名称里看到有这张表了,但查询或删除时都提示“ORA-00942表或者试图不存在”的错误,上网查了一下,是如下原因: “查询或删除 ...

  7. Unit Of Work--工作单元(二)

    回顾 上一篇我们根据工作单元的原理基于ADO.NET进行了简单的实现,但是当项目需求发生变化的时候,比如需要引入ORM框架又要兼容当前ADO.NET实现的方式时,先前的实现就无法满足这个需求了. 话就 ...

  8. 【转】ORATOP工具使用说明

    文章转自:http://lintzyuan.blogspot.jp/2014/07/oratop.html ORATOP   前言:隨著PC Server的規格及速度愈來愈快,大多數的公司摒棄大型主機 ...

  9. 开发一款高端大气上档次的android应用需要必备的知识——记于2013年末

    Android入门还是很简单的,看两本书,翻阅几篇文章,搭建了开发环境就算入门了.可是怎样开发一款完备的android应用呢,开发一款高端的android应用又需要那些知识呢,作者根据几年的开发经验做 ...

  10. CM: 使用gerrit,提交代码到CM

    1. Make sure your local git username matches with your Gerrit username, Gerrit username needs to be ...