一个通用的快速反射方法(A General Fast Method Invoker)

一个通用的快速反射方法(A General Fast Method Invoker)

普通反射方法

MethodInfo methodInfo = typeof(Person).GetMethod("Say");

methodInfo.Invoke(new Person(), new object[]{"hello"});
 

 快速反射方法

FastInvokeHandler fastInvoker = GetMethodInvoker(methodInfo);
fastInvoker(new Person(), new object[]{"hello"});

 实现,首先需要定义一个委托:

public delegate object FastInvokeHandler(object target,  object[] 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++)
    {
        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 would throw the original one, but the Method.Invoke would throw a TargetInvocationException .

 

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Luyan



China China

Member
I am currently working for a .NET framework names AgileFramework. It's introduction at here:
http://www.agilelabs.cn/agileframework

Now I'm living in China. I have been designing and developing .NET based software applications for 5+ years.

你可能感兴趣的:(.net,performance)