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. 私服 Nexus 的配置

    一.概述 1.概要 现在的项目基本都是用Maven来管理工程,这样一来在公司内容搭建一个私服就非常有必要了,这样一来可以管理公司内部用的JAR包,也可以管理第三方的各种JAR来,以免每次都要从外网的仓 ...

  2. 2.C#中通过委托Func消除重复代码

    阅读目录   一:重复的代码 二:C#中通过委托Func消除重复代码 一:重复代码    public class Persion { public string Name { get; set; } ...

  3. Android中GridView使用总结

    1.http://blog.csdn.net/hellogv/article/details/4567095  基础篇,GridView最基本的用法 2.http://my.eoe.cn/cainia ...

  4. Spark源码系列(九)Spark SQL初体验之解析过程详解

    好久没更新博客了,之前学了一些R语言和机器学习的内容,做了一些笔记,之后也会放到博客上面来给大家共享.一个月前就打算更新Spark Sql的内容了,因为一些别的事情耽误了,今天就简单写点,Spark1 ...

  5. 最近想上游戏,弄了个工作室,名"柑谷工作室"

    最近想上游戏,弄了个工作室,名"柑谷工作室",名字取得有点随便,原因是好名字都让狗用了.想当年我用的龙纹工作室,现在龙纹两字也被人用了.人家有硅谷,然后我弄个柑谷,差不多吧.算了, ...

  6. Web API 入门系列- 从一个示例开始

    1.新建Web API项目 2.新建bookModel 3.新建book web api 控制器 为了简单方便,演示系统使用内存集合持久化书籍. 4.测试web api 我们怎么方便测试web api ...

  7. ERB预处理ruby代码

    cucumber.yml 文件可以用erb预处理,这样允许你在cucumber.yml文件中使用ruby代码生成值.所以如果你有几个配置要用相同值时,你可以这样写 # config/cucumber. ...

  8. MyBatis知多少(6)表现层与业务逻辑层

    表现层 表现层负责向最终用户展示应用程序的控制方式以及数据.它还要负责所有信息的布局和格式.今天,商业应用程序最流行的表现方式应该算是Web前端了,它使用HTML和JavaScript并通 过Web浏 ...

  9. IIS限制ip访问

    1.禁止IP访问 http://jingyan.baidu.com/article/22fe7ced0462633002617f39.html 2.限制IP访问频率 http://q.cnblogs. ...

  10. NopCommerce插件学习

    在园子里看到这篇文章:http://www.cnblogs.com/haoxinyue/archive/2013/06/06/3105541.html写的非常好,我也是在此文章的基础上来一步步的学习N ...