(Http://www.cnblogs.com/kidon/archive/2006/09/06/495936.aspx) Introduction
Sometimes, I run them ss the need to dynamically invoke the method of an object, where the actual method might not be known until run-time. usually, reflecting is nice, but frequently doing it can be too slow. this article describes an alternative method for dynamic method invocation.
Background
When I read the articleFast dynamic property accessors, I was thinking about my project, it has a lots of reflecting methods in circle. But it's methods not properties. ButDynamicmethod
Reminded me, maybe I cocould useEmit
To generateDynamicmethod
To bind a special method before it can be invoked. I hope it will improve performance.
Using the code
First, I reflected out the method which will be invoked:
Methodinfo = Typeof (Person). getmethod ( " Say " );
Then, I getMethodinvoker
To invoke:
Fastinvokehandler fastinvoker = Getmethodinvoker (methodinfo );
Fastinvoker ( New Person (), New Object [] { " Hello " });
Instead of using reflection method, invoke in the past:
Methodinfo. Invoke ( New Person (), New Object [] { " Hello " }); Implementation
First, I need to define a delegate to adapt the dynamic method:
Public Delegate Object Fastinvokehandler ( Object Target,
Object [] Paramters );
It looks the same as the classMethodinfo
'SInvoke
Method. Yes, that means I can write the same code to use it like in the past.
This code generatesDynamicmethod
:
Public Static Fastinvokehandler getmethodinvoker (methodinfo)
{
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 ++ )
{
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]);
}
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]);
}
Il. emit (Opcodes. ldarg_0 );
For ( Int I = 0 ; I < Paramtypes. length; I ++ )
{
Il. emit (Opcodes. ldloc, locals [I]);
}
Il. emitcall (Opcodes. Call, methodinfo, Null );
If (Methodinfo. returntype = Typeof ( Void ))
Il. emit (Opcodes. ldnull );
Else
Emitboxifneeded (IL, methodinfo. returntype );
Il. emit (Opcodes. Ret );
Fastinvokehandler invoder =
(Fastinvokehandler) dynamicmethod. createdelegate (
Typeof (Fastinvokehandler ));
Return Invoder;
} Conclusion
Well, I think this is a general way that can be used instead of most of the reflection methods to get about 50 times performance improvement. Any suggestions for improvements are welcome.
Extra advantage (reminded by maxguernsey): if an exception occurs in your code,Fastinovker
Wocould throw the original one, butMethod. Invoke
Wocould throwTargetinvocationexception
.
Program download