C# 快速反射 IL
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的更多相关文章
- [源码]Literacy 快速反射读写对象属性,字段
Literacy 说明 Literacy使用IL指令生成方法委托,性能方面,在调用次数达到一定量的时候比反射高很多 当然,用IL指令生成一个方法也是有时间消耗的,所以在只使用一次或少数几次的情况,不但 ...
- 快速反射DataTable
public class SetterWrapper<TTarget, TValue> { private Action<TTarget, TValue> _setter; p ...
- 在 .NET 平台使用 ReflectionDynamicObject 优化反射调用代码
基于封装的原则,API 的设计者会将部分成员(属性.字段.方法等)隐藏以保证健壮性.但总有需要直接访问这些私有成员的情况. 为了访问一个类型的私有成员,除了更改 API 设计还有就是使用反射技术: p ...
- 更新Literacy
之前都没有做单元测试的啊 昨天离职了,闲着没事做了个单元测试,结果发现一堆问题....大部分都是关于值类型在IL中的操作问题... 这件事让我感觉蛋蛋隐隐发疼....以后一定要做单元测试啊.... 具 ...
- 一种简单,轻量,灵活的C#对象转Json对象的方案(续)
本文参考资料 一种简单,轻量,灵活的C#对象转Json对象的方案 [源码]Literacy 快速反射读写对象属性,字段 一段废话 之前我已经介绍了这个方案的名称为JsonBuilder,这套方案最大的 ...
- Java动态代理全面分析
代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1 主题:规定代理类和真实对象共同对外暴露的接口: 2 代理类:专门代理真实对象的类: 3 ...
- Java动态代理与Cglib库
JDK动态代理 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在 ...
- 解决你的开发烦恼——Aoite 开源前奏
Aoite(Any one item!) 一个适于任何 .Net Framework 4.0+ 项目的快速开发整体解决方案,敬请关注 Aoite GitHub. 介绍 本项目从2009年孵化(V-&g ...
- 热更新脚本C#light,ulua,Scorpio性能比较
http://www.unity蛮牛.com/thread-32861-1-1.html 测试环境: unity4.5.2 三个脚本全是源码导入 PC :处理器 Intel(R) Core(TM) ...
随机推荐
- 【C】——幻方算法
一.幻方按照阶数可分成了三类,即奇数阶幻方.双偶阶幻方.单偶阶幻方. 二.奇数阶幻方(劳伯法) 奇数阶幻方最经典的填法是罗伯法.填写的方法是: 把1(或最小的数)放在第一行正中:按以下规律排列剩下的( ...
- javaBean List Map json(转)
1.依赖的包 根据:http://json-lib.sourceforge.net/ 可见json-lib使用需要依赖一下包: 下载地址:http://download.csdn.net/down ...
- 在线读取office 文件(Word excel 等)
https://view.officeapps.live.com/op/view.aspx?src=http://www.xxx.com/uploadfile/app/11.xls src 后面的网址 ...
- Spark1.0新特性-->Spark SQL
Spark1.0出来了,变化还是挺大的,文档比以前齐全了,RDD支持的操作比以前多了一些,Spark on yarn功能我居然跑通了.但是最最重要的就是多了一个Spark SQL的功能,它能对RDD进 ...
- Devexpress HtmlEditor 上传本地图片
官方Demo地址:https://demos.devexpress.com/MVCxHTMLEditorDemos/Features/Features 控件的一定要包裹在form中 @using(Ht ...
- C primer plus 练习题 第二章
6. #include <stdio.h> void echo(); int main() { /* echo(); echo(); echo(); printf("\n&quo ...
- ivqBlog 开源博客 (angularjs + express + mongodb)
转向做全职前端差不多一年的时间了,其中学习了构建工具grunt,gulp,angularjs,coffeescript,less,sass,自己想要做全栈开发,所以自学了mongodb,nodejs, ...
- 一步步教你搭建VS环境下用C#写WebDriver脚本
一步步教你搭建VS环境下用C#写WebDriver脚本http://www.automationqa.com/forum.php?mod=viewthread&tid=3529&fro ...
- ODAC(V9.5.15) 学习笔记(十九)主键值自动生成
ODAC支持通过Oracle的序列来自动生成表的主键功能.这个过程允许在客户端自动完成,不需要过多代码.这个对一些要求自动增长字段做主键的场合非常有用.其实现步骤为: 1.数据库必须先建立生成主键的序 ...
- 转:CWnd的函数,以后可以在这儿找了!
CWnd CObject └CCmdTarget └CWnd CWnd类提供了微软基础类库中所有窗口类的基本功能.CWnd对象与Windows的窗口不同,但是两者有紧密联系.CWnd对象是由 ...