.net core 使用 DispatchProxy 实现AOP动态代理 ,.Net Framework 下Remoting核心类库RealProxy实现AOP实现动态代理

15 篇文章 0 订阅

        在学习.net core的过程中,我们已经明确被告知,Remoting将不会被支持。官方的解释是,.net framework 类型包含了太多的Runtime的内容,是一个非常重量级的服务实现,已被确定为一项有问题的体系结构。说白了就是迁移的难度很大,.net core中直接不提供了。

        既然,.net core 已经不支持RealProxy,那么就只能另起炉灶了。通过翻阅.net core的代码,终于发现了一个程序集:System.Reflection.DispatchProxy。此程序中,有一个类型DispatchProxy。(灵感还是来自于WCF。WCF是.net 中重量级的API,微软不可能不支持,通过翻阅其中的实现逻辑,终于到了RealProxy的替代方案。)     

        通过DispatchProxy提供的功能,很容易可以替代RealProxy,Remoting的问题终于比较完美的解决了

.Net Core下使用DispatchProxy实现AOP实现动态代理

/// <summary>
/// 动态代理
/// </summary>
public class MyDispatchProxy<T> : DispatchProxy
{
    private T Object { set; get; }
    public static T Create(Func<T> creator)
    {
        object proxy = DispatchProxy.Create<T, MyDispatchProxy<T>>();
        ((MyDispatchProxy<T>)proxy).Object = creator();
        return (T)proxy;
    }
    /// <summary>
    /// 创建代理实例 T:所要代理的接口类型 TInterceptor:拦截器类型
    /// </summary>
    /// <param name="parameters">拦截器构造函数参数值</param>
    /// <returns>代理实例</returns>
    public static T Create2<TInterceptor>(params object[] parameters) where TInterceptor : IDBHelper
    {
        var proxy = GetProxy(typeof(T));            
        ((MyDispatchProxy<T>)proxy).CreateInstance(typeof(TInterceptor), parameters);
        return (T)proxy;
    }

    private static object GetProxy(Type targetType)
    {
        var callexp = Expression.Call(typeof(DispatchProxy), nameof(DispatchProxy.Create), new[] { targetType, typeof(MyDispatchProxy<T>) });
        return Expression.Lambda<Func<object>>(callexp).Compile()();
    }
    private void CreateInstance(Type interceptorType, object[] parameters)
    {
        var ctorParams = parameters.Select(x => x.GetType()).ToArray();
        var paramsExp = parameters.Select(x => Expression.Constant(x));
        var newExp = Expression.New(interceptorType.GetConstructor(ctorParams), paramsExp);           
        this.Object = Expression.Lambda<Func<T>>(newExp).Compile()();
    }
    protected override object Invoke(MethodInfo targetMethod, object[] args)
    {

        Write($"开始执行 DispatchProxy获取调用的方法的名称:{targetMethod.Name}");
        var result = targetMethod.Invoke(Object, args);           
        Write($"执行完成 DispatchProxy获取调用的方法的名称:{targetMethod.Name}");
        return result;
    }
    public void Write(string msg)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine(msg);
        Console.ResetColor();
    }       
}

 System.Reflection.DispatchProxy只有一个Api,就是objecct Create<T,TProxy>() where TProxy:DispatchProxy,约束了只能传入泛型参数,并不能从方法传入类型,这就会带来很多问题。

另外一个解决方案,就是用反射来构造这个泛型方法。

使用

class Program
{
    static void Main(string[] args)
    {
        var userInfo = new UserInfo()
        {
            Account = "qq_27559331",
            Password = "123456789",
            UserName = "胡老汉"
        };                    
        //动态代理
        var dBHelpe = MyDispatchProxy<IDBHelper>.Create(() => new MySqlDBHelper());
        dBHelpe.Save(userInfo);
        Console.WriteLine("****************************************");
        IDBHelper dBHelper2 = MyDispatchProxy<IDBHelper>.Create(() => new DBHelper());
        dBHelper2.Save(userInfo);

        Console.WriteLine("\r\n使用Activator.CreateInstance<T>()\r\n");
        IDBHelper dBHelper3 = MyDispatchProxy<IDBHelper>.Create2<MySqlDBHelper>();
        dBHelper3.Save(userInfo);
        Console.WriteLine("****************************************");
        IDBHelper dBHelper4 = MyDispatchProxy<IDBHelper>.Create2<DBHelper>();
        dBHelper4.Save(userInfo);
        Console.ReadKey();
    }
}

  控制台输出

       

.Net Framework 下Remoting核心类库RealProxy 实现AOP实现动态代理

        再说迁移方案前,我们看看.net Framework中,使用Remoting的代码:通过Remoting核心类库RealProxy实现动态代理

/// <summary>
/// 真实代理
/// </summary>
/// <typeparam name="T"></typeparam>
public class MyRealProxy<T> : RealProxy
{
    private readonly T tTarget;
    public MyRealProxy(T target) : base(typeof(T))
    {
        tTarget = target;
    }

    public override IMessage Invoke(IMessage msg)
    {
        IMethodCallMessage methodCallMessage = (IMethodCallMessage)msg;
        Write($"开始执行 RealProxy获取调用的方法的名称:{methodCallMessage.MethodName}");
        object returnVaule = methodCallMessage.MethodBase.Invoke(this.tTarget, methodCallMessage.Args);
        ReturnMessage message = new ReturnMessage(returnVaule, new object[0], 0, null, (IMethodCallMessage)msg);
        Write($"执行完成 RealProxy获取调用的方法的名称:{methodCallMessage.MethodName}");
        return message;
    }
    public void Write(string msg)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine(msg);
        Console.ResetColor();
    }
}
/// <summary>
/// 透明代理
/// </summary>
public static class TransparentProxy
{
    public static T Create<T>(Func<T> creator)
    {            
        MyRealProxy<T> realProxy = new MyRealProxy<T>(creator());
        T transparentProxy = (T)realProxy.GetTransparentProxy();
        return transparentProxy;
    }
    public static T Create2<T>()
    {
        //使用Activator.CreateInstance<T>()创建类对象,类必须继承自MarshalByRefObject类或者 ContextBoundObject类
        T instance = Activator.CreateInstance<T>();
        MyRealProxy<T> realProxy = new MyRealProxy<T>(instance);
        T transparentProxy = (T)realProxy.GetTransparentProxy();
        return transparentProxy;
    }
}    

使用

class Program
{
    static void Main(string[] args)
    {
        var userInfo = new UserInfo()
        {
            Account = "qq_27559331",
            Password = "123456789",
            UserName = "胡老汉"
        };
        IDBHelper dBHelper = TransparentProxy.Create<IDBHelper>(() => new MySqlDBHelper());
        dBHelper.Save(userInfo);
        Console.WriteLine("****************************************");
        IDBHelper dBHelper2 = TransparentProxy.Create<IDBHelper>(() => new DBHelper());
        dBHelper2.Save(userInfo);
        
        Console.WriteLine("\r\n使用Activator.CreateInstance<T>()\r\n");
        IDBHelper dBHelper3 = TransparentProxy.Create2<MySqlDBHelper>();
        dBHelper3.Save(userInfo);
        Console.WriteLine("****************************************");
        IDBHelper dBHelper4 = TransparentProxy.Create2<MySqlDBHelper>();
        dBHelper4.Save(userInfo);
        Console.ReadKey();
    }
}

 控制台输出,和.net core  使用 DispatchProxy效果一样的

 

注:使用的相关自定义类内容如下

public class UserInfo
{
    public string Account { get; set; }
    public string Password { get; set; }
    public string UserName { get; set; }
}
public class DBHelper : MarshalByRefObject, IDBHelper
{
    public int Save(UserInfo userInfo)
    {
        Console.WriteLine("数据SqlServer入库");
        return default;
    }
}
public class MySqlDBHelper : MarshalByRefObject, IDBHelper
{
    public int Save(UserInfo userInfo)
    {
        Console.WriteLine("数据MySql入库");
        return default;
    }
}
public interface IDBHelper
{
    int Save(UserInfo userInfo);
}

 

 

 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡老汉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值