`
- 浏览:
770920 次
-
使用传统的.net反射机制,调用类的方法时,在调用频率大的情况下,会感觉速度很慢。最近浏览卢彦的博客时,找到一个他改进后的反射调用类。试用以后感觉效率明显提高,特推荐给大家。作者重新实现了,反射调用方法,但是调用接口和.net原有方法一致。而且调用时抛出的异常为所调用类的实际异常,不像传统方式返回为包装异常。
文章来源:http://www.codeproject.com/csharp/FastMethodInvoker.asp快速反射调用类
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Reflection;
usingSystem.Reflection.Emit;
namespaceFastMethodInvoker
{
classFastInvoke
{
publicdelegateobjectFastInvokeHandler(objecttarget,object[]paramters);
staticobjectInvokeMethod(FastInvokeHandlerinvoke,objecttarget,paramsobject[]paramters)
{
returninvoke(null,paramters);
}
publicstaticFastInvokeHandlerGetMethodInvoker(MethodInfomethodInfo)
{
DynamicMethoddynamicMethod=newDynamicMethod(string.Empty,typeof(object),newType[]{typeof(object),typeof(object[])},methodInfo.DeclaringType.Module);
ILGeneratoril=dynamicMethod.GetILGenerator();
ParameterInfo[]ps=methodInfo.GetParameters();
Type[]paramTypes=newType[ps.Length];
for(inti=0;i<paramTypes.Length;i++)
{
if(ps[i].ParameterType.IsByRef)
paramTypes[i]=ps[i].ParameterType.GetElementType();
else
paramTypes[i]=ps[i].ParameterType;
}
LocalBuilder[]locals=newLocalBuilder[paramTypes.Length];
for(inti=0;i<paramTypes.Length;i++)
{
locals[i]=il.DeclareLocal(paramTypes[i],true);
}
for(inti=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(inti=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(inti=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);
FastInvokeHandlerinvoder=(FastInvokeHandler)dynamicMethod.CreateDelegate(typeof(FastInvokeHandler));
returninvoder;
}
privatestaticvoidEmitCastToReference(ILGeneratoril,System.Typetype)
{
if(type.IsValueType)
{
il.Emit(OpCodes.Unbox_Any,type);
}
else
{
il.Emit(OpCodes.Castclass,type);
}
}
privatestaticvoidEmitBoxIfNeeded(ILGeneratoril,System.Typetype)
{
if(type.IsValueType)
{
il.Emit(OpCodes.Box,type);
}
}
privatestaticvoidEmitFastInt(ILGeneratoril,intvalue)
{
switch(value)
{
case-1:
il.Emit(OpCodes.Ldc_I4_M1);
return;
case0:
il.Emit(OpCodes.Ldc_I4_0);
return;
case1:
il.Emit(OpCodes.Ldc_I4_1);
return;
case2:
il.Emit(OpCodes.Ldc_I4_2);
return;
case3:
il.Emit(OpCodes.Ldc_I4_3);
return;
case4:
il.Emit(OpCodes.Ldc_I4_4);
return;
case5:
il.Emit(OpCodes.Ldc_I4_5);
return;
case6:
il.Emit(OpCodes.Ldc_I4_6);
return;
case7:
il.Emit(OpCodes.Ldc_I4_7);
return;
case8:
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);
}
}
}
}
效果测试程序
usingSystem;
usingSystem.Reflection;
usingSystem.Reflection.Emit;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Diagnostics;
namespaceFastMethodInvoker
{
classProgram
{
staticvoidMain(string[]args)
{
Typet=typeof(Person);
MethodInfomethodInfo=t.GetMethod("Say");
Personperson=newPerson();
stringword="hello";
Personp=null;
object[]param=newobject[]{word,p,3};
intTestTimes=100000;//测试次数,可自行调节看效果
#region传统方式反射
try
{
Stopwatchwatch=newStopwatch();
watch.Start();
for(inti=0;i<TestTimes;i++)
{
methodInfo.Invoke(person,param);
}
watch.Stop();
Console.WriteLine(TestTimes.ToString()+"timesinvokedbyReflection:"+watch.ElapsedMilliseconds+"ms");
}
catch(System.Exceptionex)
{
Console.WriteLine("传统方式反射直接错误:"+ex.Message);
Console.WriteLine("传统方式反射内部错误:"+ex.InnerException.Message);
}
#endregion
#region快速反射
try
{
Stopwatchwatch1=newStopwatch();
FastInvoke.FastInvokeHandlerfastInvoker=FastInvoke.GetMethodInvoker(methodInfo);
watch1.Start();
for(inti=0;i<TestTimes;i++)
{
fastInvoker(person,param);
}
watch1.Stop();
Console.WriteLine(TestTimes.ToString()+"timesinvokedbyFastInvoke:"+watch1.ElapsedMilliseconds+"ms");
}
catch(System.Exceptionex)
{
Console.WriteLine("快速反射错误:"+ex.Message);
}
#endregion
#region直接调用
try
{
Stopwatchwatch2=newStopwatch();
watch2.Start();
for(inti=0;i<TestTimes;i++)
{
person.Say(refword,outp,3);
}
watch2.Stop();
Console.WriteLine(TestTimes.ToString()+"timesinvokedbyDirectCall:"+watch2.ElapsedMilliseconds+"ms");
}
catch(System.Exceptionex)
{
Console.WriteLine("直接调用错误:"+ex.Message);
}
#endregion
Console.ReadLine();
}
}
publicclassPerson
{
publicvoidSay(refstringword,outPersonp,intavi)
{
word="ttt"+avi.ToString();
p=newPerson();
//thrownewSystem.Exception("出错了哦");
}
}
}
分享到:
Global site tag (gtag.js) - Google Analytics
相关推荐
基于javassist的动态编码,快速调用某个类的方法,相比于JDK的反射调用更快
jni4android是bilibili开源的一个工具,自动根据java类生成.h和.c的反射文件这个项目就是一个简单的使用示例。 jni4android项目地址 介绍 由bilibili开源的用于快速开发jni的工具,在ijkplayer中使用。主要作用是...
QLibrary 加载动态库详细用法,封装调用方法,使用简单快速、方法使用 Qt 反射更快捷
QLibrary 加载动态库详细用法,封装调用方法,使用简单快速、方法使用 Qt 反射更快捷.7z
当我在寻找一个 API 类似于 Guava 的事件总线时,我很惊讶我找不到任何足够快的用于低延迟应用程序(例如 HFT)的事件总线。 所以我决定自己做。 我见过的所有实现的主要缺点是它们都使用反射来调用侦听器方法,即...
除了java语言具有的许多安全特性以外,java对通过网络下载的类具 有一个安全防范机制(类classloader),如分配不同的名字空间以防替代本地的同名类 、字节代码检查,并提供安全管理机制(类securitymanager)让java...
1、编写一个Student对象,有“Id” + “|” + “Name” + “|” + “Gender” + “|” + “Age”四个私有成员, 并添加最后一个成员,在_初始化方法里面以"|"分隔写入所有私有成员名用于显示 2、调用类 ...
它的本质就是一个对象(JS内置的),里边有一些函数可供调用。 为什要叫做反射? 因为它能做的事情,和其他语言(Java、python等)中的反射很相似。其他语言中都叫做反射了,那就共鸣(降低学习成本?) 反射能做...
一个BeanUtils.copyProperties的小型快速替代。 起因 由于BeanUtils(Spring或Apache Commons)的copyProperties实现是利用反射实现的,它在大量调用时具有比较严重的性能问题。 BeanMapper通过javassist类库实现在...
Spring框架具有控制反转(IOC)特性,IOC旨在方便项目维护和测试,它提供了一种通过Java的反射机制对Java对象进行统一的配置和管理的方法。Spring框架利用容器管理对象的生命周期,容器可以通过扫描XML文件或类上...
推荐的模式是实例化用于配置映射的类(花费几毫秒),然后将该实例重用于数百次性能良好的操作(每轮几微秒)。 安装 选项: 任何一个 下载FastExpressionKit.cs并将其添加到您的项目中 或使用nuget包: $ ...
第一个Java程序 Java代码助手 使用IDE 使用IDE练习插件 Java程序基础 Java程序基本结构 变量和数据类型 整数运算 浮点数运算 布尔运算 字符和字符串 数组类型 流程控制 输入和输出 if判断 switch多重...
当前版本: 中提供了下一个开发版本 。用法有两种集成Dagger Reflect来替换Dagger的方法:部分反思这种方法仍然使用注释处理器来生成组件接口的实现,然后调用反射运行时。 注释处理器是完全增量的,并且不进行验证...
一个基于和简约 Java 模拟库。 特征 现场操作 允许修改任何实例字段,即使是在嵌套类中。 只需快速作弊和调用 Math.random() 就完全可以预测了: Swindler . with( " java.lang.Math$RandomNumberGeneratorHolder...
HTTP接口调用框架让 HTTP 接口调用跟调用本地方法一样自然优雅将 HTTP ...1.2.0版本后支持JDK6,之前的版本必须JDK8)技术栈动态代理反射注解自动包扫描快速开始一、添加maven依赖 <dependency> <groupId>com.github
如果一个密封类被指定为其他类的基类,则会发生编译时错误。 密封类不能同时为抽象类。 sealed 修饰符主要用于防止非有意的派生,但是它还能促使某些运行时优化。具体说来,由于密封类永远不会有任何派生类,所以...
3.4 在生成的程序集中引用一个强命名程序集 3.5 强命名程序集能防范篡改 3.6 延迟签名 3.7 私有部署强命名程序集 3.8 “运行时”如何解析类型引用 3.9 高级管理控制(配置) 3.9.1 发布者策略控制 第4章 类 型...
3.4 在生成的程序集中引用一个强命名程序集 3.5 强命名程序集能防范篡改 3.6 延迟签名 3.7 私有部署强命名程序集 3.8 “运行时”如何解析类型引用 3.9 高级管理控制(配置) 3.9.1 发布者策略控制 第4章 类 型 ...
3.4 在生成的程序集中引用一个强命名程序集 3.5 强命名程序集能防范篡改 3.6 延迟签名 3.7 私有部署强命名程序集 3.8 “运行时”如何解析类型引用 3.9 高级管理控制(配置) 3.9.1 发布者策略控制 第4章 类 型...
3.4 在生成的程序集中引用一个强命名程序集 3.5 强命名程序集能防范篡改 3.6 延迟签名 3.7 私有部署强命名程序集 3.8 “运行时”如何解析类型引用 3.9 高级管理控制(配置) 3.9.1 发布者策略控制 第4章 类 型...