推荐一个快速反射调用的类
使用传统的.net反射机制,调用类的方法时,在调用频率大的情况下,会感觉速度很慢。最近浏览卢彦的博客时,找到一个他改进后的反射调用类。试用以后感觉效率明显提高,特推荐给大家。作者重新实现了,反射调用方法,但是调用接口和.net原有方法一致。而且调用时抛出的异常为所调用类的实际异常,不像传统方式返回为包装异常。
文章来源:http://www.codeproject.com/csharp/FastMethodInvoker.asp
快速反射调用类
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.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("出错了哦");
}
}
}
转载于:https://www.cnblogs.com/haoliansheng/archive/2009/06/01/1493909.html
推荐一个快速反射调用的类相关推荐
- 推荐一个快速证件照换底色的工具超级好用
推荐一个快速证件照换底色的工具超级好用 www.yzcopen.com/img/idphoto 选择好图片转换 下载无水印照片即可 方便着急和不会ps的朋友 不去摄影棚,不用PS
- 推荐一个快速定位深度学习代码bug的炼丹神器!
文 | McGL 源 | 知乎 写深度学习网络代码,最大的挑战之一,尤其对新手来说,就是把所有的张量维度正确对齐.如果以前就有TensorSensor这个工具,相信我的头发一定比现在更浓密茂盛! Te ...
- CYQ.Data V4.5.5 版本发布[顺带开源Emit编写的快速反射转实体类FastToT类]
2019独角兽企业重金招聘Python工程师标准>>> 前言: 继上一版本:CYQ.Data 数据框架 版本发布 V4.5,刷的一下又三个多月了, 进一步的说,从 CYQ.Data ...
- 推荐一个快速部署Java,NodeJS,Python,Scala,.NET等Web应用程序的开源PASS平台
最近在Github上发现了一款神器,由Daniel Flower开发并开源的一款产品 App Runner,其Github的地址如下:https://github.com/danielflower/a ...
- java反射调用接口方法参数_Java反射调用某个类的方法(带参数和不带参数)
不多说,直接贴代码,不懂查API,现在就列取要用的方法和类. Class类: public Method getDeclaredMethod(String name, Class>... par ...
- 推荐一个快速获取时间的插件 Moment.js
Moment.js Moment.js: JavaScript 日期处理类库 官方网址: https://momentjs.com/. 中文网: http://momentjs.cn/. 这里不仅可以 ...
- java反射调用某个类的方法(带参或不带参)
Class类: public getDeclaredMethod( name, <?>... parameterTypes ...
- 就同一个Service类中,一个事务方法调用另外一个有事务的方法
目录 一.Spring 事务机制 二.Spring事务传播行为 三.场景总结 1.在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解是不会生效的 2. ...
- java反射出抽象类的实现类_java利用反射模式调用实现类
本文主讲,java利用反射模式调用接口的实现类.抽象类的继承子类.下面请听一一道来 1.第一步在src下创建com.newer.reflex包 2.在com.newer.reflex包下面建立IRef ...
最新文章
- oracle发送邮件附件,oracle发送邮件存储过程:
- mina、netty消息边界问题(采用换行符)
- unable to execute clang-tidy
- JavaScript 禁用键盘按钮
- php按照字段合并数组,PHP实现数组根据某个字段进行水平合并横向合并代码实例...
- 关于Unity中的本地存储
- 给matlab图加图注,matlab学习5-数据可视化4-gai.ppt
- JavaSE——常用类库(String类)
- Q六娱乐网整站源码分享
- 【转载】三角形测试用例
- Groovy 转换JSON和生产JSON
- 【PCBA方案】咖啡电子秤芯片方案介绍
- 蓝桥杯练习1:等差素数列
- 机房怎么制作服务器,电信服务器机房服务器搬迁地网制作方法
- 计算机桌面的快捷方式怎么打开方式,桌面快捷方式打不开,教您桌面快捷方式打不开怎么解决...
- 母亲节祝福html源码,有创意的母亲节祝福语大全
- 拼多多“出海”的三个考验?
- [魔方]魔教秘籍4:《封王-易筋经》(概要)
- 名帖47 钟繇 小楷《宣示表》
- uniapp中上传图片
热门文章
- 手把手教你用1行代码实现人脸识别 -- Python Face_recognition
- RPM方式安装MySQL5.6
- string类的实现(构造函数,析构函数,运算符重载)
- tomcat 绑定 ip 及域名,限制非法域名访问
- Android 尺寸 神图
- ubuntu 目录及文件权限 000 444 666 777(转)
- Linux下c开发 之 线程通信(转)
- CMOS图像传感器——SmartSens
- 【pyqt5学习】——最新版:配置external tools(designer、pyuic、pqrcc)
- C++总结笔记(九)—— 多态