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("出错了哦");
}
}
}
查看全文
相关阅读:
[CoreOS 转载]CoreOS实践指南(二):架设CoreOS集群
[CoreOS 转载] CoreOS实践指南(一)
[CoreOS]CoreOS 实战:CoreOS 及管理工具介绍
[SQL in Azure] Configure a VNet to VNet Connection
[SQL in Azure] Tutorial: AlwaysOn Availability Groups in Azure (GUI)
[SQL in Azure] High Availability and Disaster Recovery for SQL Server in Azure Virtual Machines
[SQL in Azure] Windows Azure Virtual Machine Readiness and Capacity Assessment
[SQL in Azure] Provisioning a SQL Server Virtual Machine on Azure
[SQL in Azure] Getting Started with SQL Server in Azure Virtual Machines
[SQL Server 2014] 微软将于年底发布新版数据库SQL Server 2014
原文地址:https://www.cnblogs.com/jehnjehn/p/2603663.html
最新文章
文件系统管理 之 Linux 查看磁盘分区、文件系统、使用情况的命令和相关工具介绍
文件系统管理 之 实例解说 fdisk 使用方法
文件系统管理 之 Linux 创建文件系统及挂载文件系统流程详解
文件系统管理 之 文件和目录访问权限设置
软件包管理 之 Fedora/Redhat 在线安装更新软件包,yum 篇 ── 给新手指南
软件包管理 之 RPM 基础 《RPM 的介绍和应用》
用户管理 之 在Linux系统中,批量添加用户的操作流程
用户管理 之 Linux 系统中的超级权限的控制
用户管理 之 Linux 用户管理工具介绍
用户管理 之 Linux 用户(User)查询篇
热门文章
用户管理 之 用户(User)和用户组(Group)配置文件详解
用户管理 之 Linux 用户(user)和用户组(group)管理概述
[转] Linux学习之CentOS(三十六)--FTP服务原理及vsfptd的安装、配置
[转载] Redis
[转载] Redis 起步
[CoreOS 转载] CoreOS实践指南(七):Docker容器管理服务
[CoreOS 转载] CoreOS实践指南(六):分布式数据存储Etcd(下)
[CoreOS 转载] CoreOS实践指南(五):分布式数据存储Etcd(上)
[CoreOS 转载] CoreOS实践指南(四):集群的指挥所Fleet
[CoreOS 转载] CoreOS实践指南(三):系统服务管家Systemd
Copyright © 2011-2022 走看看