zoukankan
html css js c++ java
推荐一个快速反射调用的类
使用传统的.net反射机制,调用类的方法时,在调用频率大的情况下,会感觉速度很慢。最近浏览
卢彦
的博客时,找到一个他改进后的反射调用类。试用以后感觉效率明显提高,特推荐给大家。作者重新实现了,反射调用方法,但是调用接口和.net原有方法一致。而且调用时抛出的异常为所调用类的实际异常,不像传统方式返回为包装异常。
文章来源:
http://www.codeproject.com/csharp/FastMethodInvoker.asp
快速反射调用类
using
System;
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;
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("出错了哦");
}
}
}
查看全文
相关阅读:
webform文件上传加水印
2017-6-6 ASP.NET Ajax版页面无刷新三级联动
2017-6-5 Ajax应用
转【 正则表达式】
2017-6-4 JQuery中的选择器和动画 弹窗遮罩
Linq 组合分页查询
2017-6-2 Linq高级查询和函数
2017-6-3 JQuery中的Dom操作和事件
WebForm母版页
WebForm内置对象:Application和ViewState、Repeater的Command用法
原文地址:https://www.cnblogs.com/jehnjehn/p/2603663.html
最新文章
WebForm(Linq增删改查)
WebForm(文件上传)
正则表达式(引用版)手机号、身份证号、邮箱
正则表达式(基本编码)
母版页的应用
mazing ASP.NET Core 2.0【转】
组合查询分页代码
Webform(条件查询)
Webform——JQuery基础(选择器、事件、DOM操作)
Webform--LinQ 分页组合查询
热门文章
LinQ简单增、删、改、查
web设计页面跳转的方法
Ajax
jQuery ajax
JavaScript事件的属性列表
JQUERY 刷新关闭页面
JQUERY / JS 判断数据类型方法(限制文本框类型输入)
JavaScript复习
2017-6-10 ASP.NET邮箱认证并进行判断
Webform 验证码制作
Copyright © 2011-2022 走看看