提高反射的效率

使用委托调用比直接调用慢10%,使用反射是直接调用的600倍,当然这取决于方法内部是否还外拉数据,但是反射转委托调用的好处显而易见
所以我们需要使用反射和泛型方法来动态创建委托,并通过这些委托来调用特定的方法
先创建一个带有返回值的

public class RegisterDemo
{
    private static RegisterManager _registerManager ;
    public static void GetRegister()
    {
        MethodInfo methodInfo = typeof(RegisterManager).GetMethod("RegiserScoped", new Type[] { typeof(Type), typeof(Type) });
        Func<RegisterManager, object, object, object> Register = MagicMethod<RegisterManager>(methodInfo);

        Register(_registerManager, typeof(A), typeof(B));
    }

    static Func<T, object, object, object> MagicMethod<T>(MethodInfo methodInfo) where T : class
    {
        MethodInfo genericHelper = typeof(RegisterDemo).GetMethod("MagicMethodHelper", BindingFlags.Static | BindingFlags.NonPublic);
        MethodInfo constructHelper = genericHelper.MakeGenericMethod(typeof(T), methodInfo.GetParameters()[0].ParameterType, methodInfo.GetParameters()[1].ParameterType,methodInfo.ReturnType);
        
        object ret = constructHelper.Invoke(null, new object[] { methodInfo });
        return (Func<T, object, object, object>)ret;
    }

    static Func<TTarget, object, object, object> MagicMethodHelper<TTarget, TParam1, TParam2, TReturn>(MethodInfo method)
        where TTarget : class, new()
    {
        // 将方法转为委托
        Func<TTarget, TParam1, TParam2, TReturn> func = (Func<TTarget, TParam1, TParam2, TReturn>)Delegate.CreateDelegate
            (typeof(Func<TTarget, TParam1, TParam2, TReturn>), method);

        // 创建一个更弱的委托调用上面的委托
        Func<TTarget, object, object, object> ret = (TTarget target, object param1, object param2) => func(target, (TParam1)param1, (TParam2)param2);
        return ret;
    }
}
public class RegisterManager
{
    public string RegiserScoped(Type from,Type to) 
    {
        Console.WriteLine(123);
        return "1111";
    }
}
public class A
{

}
public class B { }

我们需要理解委托的参数含义,一个目标值,两个参数,一个返回值,注意看我们的RegiserScoped方法
它的返回值是string,目标值是RegisterManager,参数是两个Type,那么我们的委托需要签名,
在MagicMethodHelper方法中返回值是Func<TTarget, object, object, object>
其中TTarget指的是RegisterManager,后面三个object分别指的是两个参数Type,和返回值string
同理,我们写void类型的时候不需要返回值,这个时候用Action

public class RegisterDemo2
{
    private static RegisterManager2 _registerManager;
    public static void GetRegister()
    {
        MethodInfo methodInfo = typeof(RegisterManager2).GetMethod("RegiserScoped", new Type[] { typeof(Type), typeof(Type) });
        Action<RegisterManager2, object, object> Register = MagicMethod<RegisterManager2>(methodInfo);

        Register(_registerManager, typeof(A2), typeof(B2));
    }
    static Action<T, object, object> MagicMethod<T>(MethodInfo methodInfo) where T : class
    {
        MethodInfo genericHelper = typeof(RegisterDemo2).GetMethod("MagicMethodHelper", BindingFlags.Static | BindingFlags.NonPublic);
        MethodInfo constructHelper = genericHelper.MakeGenericMethod(typeof(T), methodInfo.GetParameters()[0].ParameterType, methodInfo.GetParameters()[1].ParameterType);

        object ret = constructHelper.Invoke(null, new object[] { methodInfo });
        return (Action<T, object, object>)ret;
    }

    static Action<TTarget, object, object> MagicMethodHelper<TTarget, TParam1, TParam2>(MethodInfo method)
        where TTarget : class, new()
    {
        // 将方法转为委托
        Action<TTarget, TParam1, TParam2> action = (Action<TTarget, TParam1, TParam2>)Delegate.CreateDelegate
            (typeof(Action<TTarget, TParam1, TParam2>), method);

        // 创建一个更弱的委托调用上面的委托
        Action<TTarget, object, object> ret = (TTarget target, object param1, object param2) => action(target, (TParam1)param1, (TParam2)param2);
        return ret;
    }
}

public class RegisterManager2
{
    public void RegiserScoped(Type from, Type to)
    {
        Console.WriteLine(123);
    }
}

public class A2
{

}

public class B2
{

}

在RegisterManager2中的RegiserScoped方法没有返回值,所以我们的委托需要用到Action,同上
原文来自

https://codeblog.jonskeet.uk/2008/08/09/making-reflection-fly-and-exploring-delegates/

本文作者:孤沉

本文链接:https://www.cnblogs.com/guchen33/p/18075928

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   孤沉  阅读(22)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开