Using System;
Using System. Reflection;
Using System. Reflection. Emit;
Using System. Collections. Generic;
Using System. Text;
Using System. Diagnostics;
Namespace FastMethodInvoker
{
Public delegate object FastInvokeHandler (object target, object [] paramters );
Public delegate void SayHandler (string word );
Class Program
{
Static object InvokeMethod (FastInvokeHandler invoke, object target, params object [] paramters)
{
Return invoke (null, paramters );
}
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 };
Stopwatch watch = new Stopwatch ();
Watch. Start ();
For (int I = 0; I <1000000; I ++)
{
MethodInfo. Invoke (person, param );
}
Watch. Stop ();
Console. WriteLine ("1000000 times invoked by Reflection:" + watch. ElapsedMilliseconds + "ms ");
Stopwatch wattings = new Stopwatch ();
FastInvokeHandler fastInvoker = GetMethodInvoker (methodInfo );
Watch1.Start ();
For (int I = 0; I <1000000; I ++)
{
FastInvoker (person, param );
}
Watch1.Stop ();
Console. WriteLine ("1000000 times invoked by FastInvoke:" + watch1.ElapsedMilliseconds + "ms ");
Stopwatch watch2 = new Stopwatch ();
Watch2.Start ();
For (int I = 0; I <1000000; I ++)
{
Person. Say (ref word, out p, 3 );
}
Watch2.Stop ();
Console. WriteLine ("1000000 times invoked by DirectCall:" + watch2.ElapsedMilliseconds + "ms ");
Console. ReadLine ();
}
Private 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 );
}
}
}
Public class Person
{
Public void Say (ref string word, out Person p, int avi)
{
Word = "ttt" + avi. ToString ();
P = new Person ();
}
}
}
Author Tang ruixin