`
jinvasshole
  • 浏览: 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