翼度科技»论坛 编程开发 .net 查看内容

05-《AspNetCore》-AOP

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
AOP


面向切面编程AOP的对面向对象编程OOP的一个补充,它的特点是将系统逻辑和业务逻辑采取《非侵入式》分离。我们把系统封装成一个一个的切面(单一职责)进行顺意编排组合,插入(织入)到业务逻辑的执行过程(织入点)。
系统逻辑:异常处理,身份认证,授权,mvc,数据校验,事务处理。
业务逻辑:就是我们的业务Service。
切面:用于封装系统逻辑,比如身份认证filter,或者中间件
切入点:就是管道的位置。名词
织入:就是插入到管道的切入点的过程。动词
AOP的特点:
1.非侵入式
2.低耦合
3.代码服用
4.单一职责
5.可插拔
实现方式:
1.管道链,比如aspnetcore的中间件,mvc中的Filter
2.静态代理:思考如何加强一个List,使得在插入时打印日志?
3.动态代理:Emit
4.三种模式都需要通过一些技术进行串联,实现链式调用,构成管道。静态代理通过接口进行串联,动态代理通过反射进行串联。管道通过接口获取委托进行串联。委托本质也是接口。
代理:就是增强,代理对象必须尽量实现目标对象的功能,在此基础上进行加强。比如vpn,你的电脑的网络就是目标对象,vpn就是代理服务,代理服务起码得实现联网功能吧,然后对网络进行加强,访问到一些你的本机网络访问不到的东西。
掌握了AOP技术我们可以实现很多好处,做到非侵入式的增强业务逻辑。
  1. //侵入式方案,把这个看懂。后面就是围绕这个开展,高出非侵入式
  2. public static void A()
  3. {
  4.     Console.WriteLine("A:开始");
  5.     B();//A,B的调用关系强行绑定,有侵入性
  6.     Console.WriteLine("A:结束");
  7. }
  8. public static void B()
  9. {
  10.     Console.WriteLine("B:开始");
  11.     C();
  12.     Console.WriteLine("B:结束");
  13. }
  14. public static void C()
  15. {
  16.     Console.WriteLine("Hello World");
  17. }
  18. public static void Dobasic()
  19. {
  20.     A();
  21. }
复制代码
静态代理

1.代理就是实现目标对象的标准(接口),在目标方法执行之前和之后进行逻辑织入的过程。代理的目的就是为了加强。代理不负责实现接口,一般通过target来实现接口。即代理除了可以增强之外还能简化接口的实现。
2.静态代理就是在代理之前就已经确定了代理关系。需要自己实现标准并编写代理类。代理类中的逻辑只能代理一些标准(实现多个接口)。无法代理所有标准。
3.静态代理可以实现不改变目标对象的源码的情况下进行加强,完成目标对象的能力,并且在此基础之上进行加强。
4.可以简化实现的成本,不改变业务代码,只需要编写额外的增强逻辑。不需要关系具体的业务实现。
5.代理和代理直接通过接口可以进行互相代理,链式调用,顺意编排组合,实现系统的多样化。
  1. /// <summary>
  2. /// 定义标准1
  3. /// </summary>
  4. public interface IPhoneService
  5. {
  6.     string Mobile { get; set; }
  7.     string Message { get; set; }
  8.     void Send();
  9. }
  10. //实现标准-不是代理模式
  11. public class PhoneService : IPhoneService
  12. {
  13.     public string Mobile { get; set; }
  14.     public string Message { get; set; }
  15.     public PhoneService(string mobile, string message)
  16.     {
  17.         Mobile = mobile;
  18.         Message = message;
  19.     }
  20.     public virtual void Send()
  21.     {
  22.         Console.WriteLine($"已发送短信:{Message}到{Mobile}");
  23.     }
  24. }
  25. //代理模式:
  26. //1.实现目标对象的标准
  27. //2.依赖目标对象(被代理对象)
  28. //3.业务织入
  29. public class PhoneServiceProxy : IPhoneService//实现标准
  30. {
  31.     private readonly IPhoneService _target;
  32.     public PhoneServiceProxy1(IPhoneService target)
  33.     {
  34.         _target = target;
  35.     }
  36.     public string Mobile { get => _target.Mobile; set => _target.Mobile = value; }
  37.     public string Message { get => _target.Message; set => _target.Message = value; }
  38.     /// <summary>
  39.     /// 子类重写父类方法
  40.     /// </summary>
  41.     public void Send()
  42.     {
  43.         Console.WriteLine("Proxy1:已对手机号进行验证");
  44.         _target.Send();
  45.         Console.WriteLine("Proxy1:已确认对方已经收到");
  46.     }
  47. }
复制代码
  1. /// <summary>
  2. /// 定义标准1
  3. /// </summary>
  4. public interface IPhoneService
  5. {
  6.     string Mobile { get; set; }
  7.     string Message { get; set; }
  8.     void Send();
  9. }
  10. /// <summary>
  11. /// 定义标准2
  12. /// </summary>
  13. public interface IEmailService
  14. {
  15.     string Email { get; set; }
  16.     string Message { get; set; }
  17.     void Send();
  18. }
  19. /// <summary>
  20. /// 业务逻辑1
  21. /// </summary>
  22. public class PhoneService : IPhoneService
  23. {
  24.     public string Mobile { get; set; }
  25.     public string Message { get; set; }
  26.     public PhoneService(string mobile, string message)
  27.     {
  28.         Mobile = mobile;
  29.         Message = message;
  30.     }
  31.     public virtual void Send()
  32.     {
  33.         Console.WriteLine($"已发送短信:{Message}到{Mobile}");
  34.     }
  35. }
  36. /// <summary>
  37. /// 业务逻辑2
  38. /// </summary>
  39. public class EmailService : IEmailService
  40. {
  41.     public string Email { get; set; }
  42.     public string Message { get; set; }
  43.     public EmailService(string email, string message)
  44.     {
  45.         Email = email;
  46.         Message = message;
  47.     }
  48.     public virtual void Send()
  49.     {
  50.         Console.WriteLine($"已发送邮件:{Message}到{Email}");
  51.     }
  52. }
  53. /// <summary>
  54. /// 切面1:校验能力(系统逻辑)
  55. /// taget方式
  56. /// </summary>
  57. public class PhoneServiceProxy1
  58.     : IPhoneService//实现标准1
  59. {
  60.     private readonly IPhoneService _target;
  61.     public PhoneServiceProxy1(IPhoneService target)
  62.     {
  63.         _target = target;
  64.     }
  65.     /// <summary>
  66.     /// 子类重写父类方法
  67.     /// </summary>
  68.     public void Send()
  69.     {
  70.         Console.WriteLine("Proxy1:已对手机号进行验证");
  71.         _target.Send();
  72.         Console.WriteLine("Proxy1:已确认对方已经收到");
  73.     }
  74. }
  75. /// <summary>
  76. /// 切面2:加速能力(系统逻辑)
  77. /// </summary>
  78. public class PhoneServiceProxy2
  79.    : IPhoneService//实现标准1
  80. {
  81.     private readonly IPhoneService _target;
  82.     public PhoneServiceProxy2(IPhoneService target)
  83.     {
  84.         _target = target;
  85.     }
  86.     /// <summary>
  87.     /// 子类重写父类方法
  88.     /// </summary>
  89.     public void Send()
  90.     {
  91.         Console.WriteLine("Proxy2:已开启加速通道");
  92.         _target.Send();
  93.         Console.WriteLine("Proxy2:已关闭加速通道");
  94.     }
  95. }
  96. //test
  97. public static void TestStaticProxy()
  98. {
  99.     //目标对象
  100.     IPhoneService target = new PhoneService("10088", "你好啊!");
  101.     //切面1:验证,对target进行代理
  102.     IPhoneService proxy1 = new PhoneServiceProxy1(target);
  103.     //切面2:加速,对proxy1进行代理
  104.     IPhoneService proxy2 = new PhoneServiceProxy2(proxy1);
  105.     //执行
  106.     proxy2.Send();
  107.     //思考如果要实现IEmailService标准,是不是要重写实现类了?
  108. }
复制代码
动态代理

Castle.Core

动态代理和静态代理的区别就是,代理类由工具生成,需要在运行时确认代理类已经代理关系。代理类中的逻辑写到拦截器里面,可以进行复用。缺点是性能差。里面涉及到大量反射技术。
Castle.Core:原理就是通过子类继承父类或者实现父类标准,通过Castle.Core自动帮你生成代理类,通过一个叫拦截器的东西编写代理类要执行的业务逻辑。Castle.Core会帮你生成代理类,并将拦截器织入到代理类中。
动态代理通过invocation进行串联,本质是反射。
  1. /// <summary>
  2. /// 定义标准1
  3. /// </summary>
  4. public interface IPhoneService
  5. {
  6.     string Mobile { get; set; }
  7.     string Message { get; set; }
  8.     void Send();
  9. }
  10. /// <summary>
  11. /// 定义标准2
  12. /// </summary>
  13. public interface IEmailService
  14. {
  15.     string Email { get; set; }
  16.     string Message { get; set; }
  17.     void Send();
  18. }
  19. /// <summary>
  20. /// 业务逻辑1
  21. /// </summary>
  22. public class PhoneService : IPhoneService
  23. {
  24.     public string Mobile { get; set; }
  25.     public string Message { get; set; }
  26.     public PhoneService(string mobile, string message)
  27.     {
  28.         Mobile = mobile;
  29.         Message = message;
  30.     }
  31.     public virtual void Send()
  32.     {
  33.         Console.WriteLine($"已发送短信:{Message}到{Mobile}");
  34.     }
  35. }
  36. /// <summary>
  37. /// 业务逻辑2
  38. /// </summary>
  39. public class EmailService : IEmailService
  40. {
  41.     public string Email { get; set; }
  42.     public string Message { get; set; }
  43.     public EmailService(string email, string message)
  44.     {
  45.         Email = email;
  46.         Message = message;
  47.     }
  48.     public virtual void Send()
  49.     {
  50.         Console.WriteLine($"已发送邮件:{Message}到{Email}");
  51.     }
  52. }
  53. /// <summary>
  54. /// 代理1:任意标准
  55. /// </summary>
  56. public class ShareInterceptor1 : IInterceptor
  57. {
  58.     public void Intercept(IInvocation invocation)
  59.     {
  60.         Console.WriteLine("Proxy1:已对接收方进行验证");
  61.         invocation.Proceed();//执行下一个拦截器或者目标方法
  62.         Console.WriteLine("Proxy1:已确认对方已经收到");
  63.     }
  64. }
  65. /// <summary>
  66. /// 代理2:任意标准
  67. /// </summary>
  68. public class ShareInterceptor2 : IInterceptor
  69. {
  70.     public void Intercept(IInvocation invocation)
  71.     {
  72.         Console.WriteLine("Proxy2:已开启加速通道");
  73.         invocation.Proceed();//执行下一个拦截器或者目标方法
  74.         Console.WriteLine("Proxy2:已关闭加速通道");
  75.     }
  76. }
  77. //通过Castel生成代理类
  78. public static void TestDynamicProxy1()
  79. {
  80.     //创建代理生成器
  81.     var generator = new ProxyGenerator();
  82.     var target1 = new PhoneService("10088", "你好啊!");
  83.     var target2 = new EmailService("1123@116.com", "你好啊!");
  84.     var interceptor1 = new ShareInterceptor1();//代理1,拦截器1,不需要去实现指定的标准
  85.     var interceptor2 = new ShareInterceptor2();//代理2,拦截器2,不需要去实现指定的标准
  86.     //使用代理1和代理2去代理手机的标准
  87.     IPhoneService dynamicProxy1 = generator.CreateInterfaceProxyWithTarget<IPhoneService>(target1, interceptor1, interceptor2);
  88.     dynamicProxy1.Send();
  89.     //代理邮件的标准
  90.     IEmailService dynamicProxy2 = generator.CreateInterfaceProxyWithTarget<IEmailService>(target2, interceptor1, interceptor2);
  91.     dynamicProxy2.Send();
  92. }
复制代码
手写Castle.Core的代理类

思考:
generator创建的是什么类型的实列?显然不可能是已有的类型。因为它把拦截器织入进去了。而且没有修改我们的代码,站在面向对象的角度来看只能是实现了我们的接口,Emit动态实现了下面的代码
多个拦截器和目标对象(被代理者)通过Invocation进行串联。Invocation中的Arguments完成链式调用。
手动通过Invocation进行串联
  1. //假设有三个拦截器
  2. //第一个拦截器invocation1:Proxy=interceptor2,Method=Intercept,argument=invocation2
  3. //第二个拦截器invocation2:Proxy=interceptor3,Method=Intercept,argument=invocation3
  4. //第三个拦截器invocation2:Proxy=target,Method=method,argument=arguments
  5. //手动实现
  6. public IInvocation GetInvocation(Stack<IInterceptor> stack, object target, Method method, objuect arguments)
  7. {
  8.     var invocation1 = new Invocation()
  9.     {
  10.         Proxy = interceptor2,
  11.         Method = typeof(IInterceptor).GetMethod(nameof(IInterceptor.Intercept)),
  12.         Arguments = new object[]
  13.         {
  14.             new Invocation()
  15.             {
  16.                 Proxy = interceptor3,
  17.                 Method = typeof(IInterceptor).GetMethod(nameof(IInterceptor.Intercept)),
  18.                 Arguments = new object[]
  19.                 {
  20.                     new Invocation()
  21.                     {
  22.                         Proxy = target,
  23.                         Method = method,
  24.                         Arguments = arguments
  25.                     }  
  26.                 }
  27.             }
  28.         }
  29.     }
  30. }
  31. //递归实现
  32. public IInvocation GetInvocation(Stack<IInterceptor> stack, object target, Method method, objuect arguments)
  33. {
  34.     if(stack.Any())
  35.     {
  36.         var proxy = stack.Pop();
  37.         return new Invocation()
  38.         {
  39.                   Proxy = proxy,
  40.             Method = typeof(IInterceptor).GetMethod(nameof(IInterceptor.Intercept)),
  41.             Agrumtns = GetInvocation(stack,method,argumtns)
  42.         };
  43.     }
  44.     else
  45.     {
  46.         return new Invocation()
  47.         {
  48.                   Proxy = target,
  49.             Method = method,
  50.             Agrumtns = arguments
  51.         };
  52.     }
  53. }
复制代码
  1. //Castel.Core自动帮我们生成了下面这个类
  2. public class CastelPhoneServiceProxy : IPhoneService
  3. {
  4.     private IPhoneService _taget;
  5.     private IInterceptor[] _interceptors;
  6.     public CastelPhoneServiceProxy(IPhoneService taget, IInterceptor[] interceptors)
  7.     {
  8.         _taget = taget;
  9.         _interceptors = interceptors;
  10.     }
  11.     public string Mobile { get => _taget.Mobile; set => _taget.Mobile = value; }
  12.     public string Message { get => _taget.Message; set => _taget.Message = value; }
  13.     public void Send()
  14.     {
  15.         var stack = new Stack<IInterceptor>(_interceptors.Reverse());
  16.         if (stack.Any())
  17.         {
  18.             var item = stack.Pop();
  19.             var invocation = GetNextInvocation(stack);
  20.             item.Intercept(invocation);
  21.         }
  22.         else
  23.         {
  24.             _taget.Send();
  25.         }
  26.     }
  27.     /// <summary>
  28.     /// 递归获取Invocaltion
  29.     /// </summary>
  30.     /// <param name="stack"></param>
  31.     /// <returns></returns>
  32.     private IInvocation GetNextInvocation(Stack<IInterceptor> stack)
  33.     {
  34.         if (stack.Any())
  35.         {
  36.             var next = stack.Pop();
  37.             return new Invocaltion
  38.             {
  39.                 Arguments = new object[]
  40.                 {
  41.                     //递归
  42.                     GetNextInvocation(stack)
  43.                 },
  44.                 Proxy = next,
  45.                 Method = typeof(IInterceptor).GetMethod(nameof(IInterceptor.Intercept)) ?? throw new NullReferenceException()
  46.             };
  47.         }
  48.         else
  49.         {
  50.             return new Invocaltion
  51.             {
  52.                 Arguments = new object[]
  53.                 {
  54.                 },
  55.                 Proxy = _taget,
  56.                 Method = _taget.GetType().GetMethod(nameof(IPhoneService.Send)) ?? throw new NullReferenceException()
  57.             };
  58.         }
  59.     }
  60. }
  61. //实现一些castle.core的接口
  62. public class Invocaltion : IInvocation
  63. {
  64.     public object[] Arguments { get; set; }
  65.     public Type[] GenericArguments { get; set; }
  66.     public object InvocationTarget { get; set; }
  67.     public MethodInfo Method { get; set; }
  68.     public MethodInfo MethodInvocationTarget { get; set; }
  69.     public object Proxy { get; set; }
  70.     public object ReturnValue { get; set; }
  71.     public Type TargetType { get; set; }
  72.     public IInvocationProceedInfo CaptureProceedInfo()
  73.     {
  74.         throw new NotImplementedException();
  75.     }
  76.     public object GetArgumentValue(int index)
  77.     {
  78.         throw new NotImplementedException();
  79.     }
  80.     public MethodInfo GetConcreteMethod()
  81.     {
  82.         throw new NotImplementedException();
  83.     }
  84.     public MethodInfo GetConcreteMethodInvocationTarget()
  85.     {
  86.         throw new NotImplementedException();
  87.     }
  88.     public void Proceed()
  89.     {
  90.         Method.Invoke(Proxy, Arguments);
  91.     }
  92.     public void SetArgumentValue(int index, object value)
  93.     {
  94.         throw new NotImplementedException();
  95.     }
  96. }
复制代码
EMIT实现
  1. //链路器
  2. public class EmitInvocation
  3. {
  4.     private object? proxy;
  5.     private MethodInfo? method;
  6.     private object[]? arguments;
  7.     public EmitInvocation(object? proxy, MethodInfo? method, object[]? arguments)
  8.     {
  9.         this.proxy = proxy;
  10.         this.method = method;
  11.         this.arguments = arguments;
  12.     }
  13.     public void Proceed()
  14.     {
  15.         method?.Invoke(proxy, arguments);
  16.     }
  17. }
  18. //拦截器
  19. public interface IEmitInteceptor
  20. {
  21.     void Intercept(EmitInvocation invocation);
  22. }
  23. //实现拦截器1
  24. public class EmitInteceptor1 : IEmitInteceptor
  25. {
  26.     public void Intercept(EmitInvocation invocation)
  27.     {
  28.         Console.WriteLine("prox1:start");
  29.         invocation.Proceed();
  30.         Console.WriteLine("prox1:end");
  31.     }
  32. }
  33. //实现拦截器1
  34. public class EmitInteceptor2 : IEmitInteceptor
  35. {
  36.     public void Intercept(EmitInvocation invocation)
  37.     {
  38.         Console.WriteLine("prox2:start");
  39.         invocation.Proceed();
  40.         Console.WriteLine("prox2:end");
  41.     }
  42. }
  43. //该工具类帮助我们少写emit代码
  44. public static class EmitProxyInvoker
  45. {
  46.     public static EmitInvocation GetNextInvocation(Stack<IEmitInteceptor> stack, MethodInfo method, object target, object[] arguments)
  47.     {
  48.         if (stack.Any())
  49.         {
  50.             var next = stack.Pop();
  51.             arguments = new object[]
  52.             {
  53.                 //递归
  54.                 GetNextInvocation(stack, method, target, arguments)
  55.             };
  56.             return new EmitInvocation(next, typeof(IEmitInteceptor).GetMethod(nameof(IEmitInteceptor.Intercept)), arguments);
  57.         }
  58.         else
  59.         {
  60.             return new EmitInvocation(target, method, arguments);
  61.         }
  62.     }
  63.     public static void Invoke(IEmitInteceptor[] interceptors, MethodInfo method, object target, object[] arguments)
  64.     {
  65.         var stack = new Stack<IEmitInteceptor>(interceptors.Reverse());
  66.         if (stack.Any())
  67.         {
  68.             var item = stack.Pop();
  69.             var invocation = GetNextInvocation(stack, method, target, arguments);
  70.             item.Intercept(invocation);
  71.         }
  72.         else
  73.         {
  74.             method.Invoke(target, arguments);
  75.         }
  76.     }
  77. }
  78. //业务接口
  79. public interface IEmitService
  80. {
  81.     void Send();
  82. }
  83. //将来要生成的代理类
  84. public class EmitServiceProxy : IEmitService
  85. {
  86.     private object _target;
  87.     private IEmitInteceptor[] _inteceptors;
  88.     public EmitService()
  89.     {
  90.     }
  91.     public void Send()
  92.     {
  93.         var method = _target.GetType().GetMethod(nameof(EmitService.Send));
  94.         var arguments = new object[] { };
  95.         EmitProxyInvoker.Invoke(_inteceptors, method, _target, new object[] { });
  96.     }
  97. }
  98. public static class EmitProxyGenerator
  99. {
  100.     static AssemblyBuilder _assemblyBuilder;
  101.     static ModuleBuilder _moduleBuilder;
  102.     static EmitProxyGenerator()
  103.     {
  104.         //创建一个程序集
  105.         var assemblyName = new AssemblyName("DynamicProxies");
  106.         _assemblyBuilder = AssemblyBuilder
  107.             .DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
  108.         //创建一个模块
  109.         _moduleBuilder = _assemblyBuilder.DefineDynamicModule("Proxies");
  110.     }
  111.     public static TInterface Create<TInterface>(object target, params IEmitInteceptor[] inteceptor)
  112.         where TInterface : class
  113.     {
  114.         
  115.         #region 定义类型
  116.         //定义一个class,如果这个类型已定义直接返回,缓存
  117.         var typeName = $"{target.GetType().Name}EmitProxy";
  118.         var typeBuilder = _moduleBuilder.DefineType(
  119.             typeName,
  120.             TypeAttributes.Public,typeof(object),
  121.             new Type[]
  122.             {
  123.                 typeof(TInterface)
  124.             });
  125.         #endregion
  126.         #region 定义字段
  127.         //定义字段
  128.         var targetFieldBuilder = typeBuilder.DefineField("target", typeof(object), FieldAttributes.Private);
  129.         var inteceptorFieldBuilder = typeBuilder.DefineField("inteceptor", typeof(IEmitInteceptor[]), FieldAttributes.Private);
  130.         #endregion
  131.         #region 定义构造器
  132.         //定义构造器
  133.         var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.ExplicitThis, new Type[]
  134.         {
  135.             typeof(object),
  136.             typeof(IEmitInteceptor[])
  137.         });
  138.         //获取IL编辑器
  139.         var generator = constructorBuilder.GetILGenerator();
  140.         generator.Emit(OpCodes.Ldarg_0);//加载this
  141.         generator.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes) ?? throw new InvalidOperationException());
  142.         generator.Emit(OpCodes.Nop);
  143.         generator.Emit(OpCodes.Nop);
  144.         // this.age = age;
  145.         generator.Emit(OpCodes.Ldarg_0);//加载this
  146.         generator.Emit(OpCodes.Ldarg_1);//加载target参数
  147.         generator.Emit(OpCodes.Stfld, targetFieldBuilder);//加载target字段
  148.         // this.name = name;
  149.         generator.Emit(OpCodes.Ldarg_0);//加载this
  150.         generator.Emit(OpCodes.Ldarg_2);//加载inteceptor参数
  151.         generator.Emit(OpCodes.Stfld, inteceptorFieldBuilder);//加载inteceptor字段
  152.         generator.Emit(OpCodes.Ret);
  153.         #endregion
  154.         #region 实现接口
  155.         var methods = typeof(TInterface).GetMethods();
  156.         foreach (var item in methods)
  157.         {
  158.             var parameterTypes = item.GetParameters().Select(s => s.ParameterType).ToArray();
  159.             var methodBuilder = typeBuilder.DefineMethod(item.Name,
  160.                 MethodAttributes.Public| MethodAttributes.Final |MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.HideBySig,
  161.                 CallingConventions.Standard|CallingConventions.HasThis,
  162.                 item.ReturnType,
  163.                 parameterTypes);
  164.             var generator1 = methodBuilder.GetILGenerator();
  165.             //init
  166.             var methodInfoLocal = generator1.DeclareLocal(typeof(MethodInfo));
  167.             var argumentLocal = generator1.DeclareLocal(typeof(object[]));
  168.             generator1.Emit(OpCodes.Nop);
  169.             generator1.Emit(OpCodes.Ldarg_0);
  170.             generator1.Emit(OpCodes.Ldfld, targetFieldBuilder);
  171.             generator1.Emit(OpCodes.Callvirt, typeof(Type).GetMethod(nameof(Type.GetType),Type.EmptyTypes));
  172.             generator1.Emit(OpCodes.Ldstr, item.Name);
  173.             generator1.Emit(OpCodes.Callvirt, typeof(Type).GetMethod(nameof(Type.GetMethod), new Type[] { typeof(string) }));
  174.             generator1.Emit(OpCodes.Stloc, methodInfoLocal);
  175.             generator1.Emit(OpCodes.Ldc_I4_0);
  176.             generator1.Emit(OpCodes.Newarr, typeof(object));
  177.             generator1.Emit(OpCodes.Stloc, argumentLocal);
  178.             generator1.Emit(OpCodes.Ldarg_0);
  179.             generator1.Emit(OpCodes.Ldfld, inteceptorFieldBuilder);
  180.             generator1.Emit(OpCodes.Ldloc_0);
  181.             generator1.Emit(OpCodes.Ldarg_0);
  182.             generator1.Emit(OpCodes.Ldfld, targetFieldBuilder);
  183.             generator1.Emit(OpCodes.Ldc_I4_0);
  184.             generator1.Emit(OpCodes.Newarr, typeof(object));
  185.             generator1.Emit(OpCodes.Call, typeof(EmitProxyInvoker).GetMethod(nameof(EmitProxyUtil.Invoke)));
  186.             generator1.Emit(OpCodes.Nop);
  187.             generator1.Emit(OpCodes.Ret);
  188.         }
  189.         #endregion
  190.         //创建:这个type可以用一个线程安全的字典缓存起来,第二次需要这个代理类的时候,就不需要在生成一次emit代码了。
  191.         var type = typeBuilder.CreateType() ?? throw new ArgumentException();
  192.         var instance = Activator.CreateInstance(type, target, inteceptor);
  193.         return (TInterface)instance;
  194.     }
  195. }
复制代码
容器支持
  1. public class DbContext
  2. {
  3.    
  4. }
  5. public class AService
  6. {
  7.     public DbContext DbContext { get; }
  8.    
  9.     public AService(DbContext context)
  10.     {
  11.         DbContext = context;
  12.     }
  13. }
  14. public static void Test()
  15. {
  16.     var services = new ServiceCollection();
  17.     services.AddScoped<DbContext>();
  18.     var generator = new ProxyGenerator();
  19.     //泛型-不支持动态注入
  20.     services.AddScoped(sp =>
  21.     {
  22.         //通过容器解析依赖
  23.         var target = ActivatorUtilities.CreateInstance<AService>(sp);
  24.         return generator.CreateClassProxyWithTarget(target);
  25.     });
  26.     //反射-可以扫描批量注入
  27.     services.AddScoped(typeof(AService), sp =>
  28.     {
  29.         //通过容器解析依赖
  30.         var target = ActivatorUtilities.CreateInstance(sp, typeof(AService));
  31.         return generator.CreateClassProxyWithTarget(target);
  32.     });
  33. }
复制代码
管道方式

委托方式

1.通过委托构建管道
  1. public delegate Task RequestDelegate(HttpContext context);
  2. public class HttpContext
  3. {
  4. }
  5. public class ApplicationBuilder
  6. {
  7.     private readonly List<Func<RequestDelegate, RequestDelegate>> _componen
  8.     public void Use(Func<RequestDelegate, RequestDelegate> middleware)
  9.     {
  10.         _components.Add(middleware);
  11.     }
  12.     public void Use(Func<HttpContext, Func<Task>, Task> middleware)
  13.     {
  14.         _components.Add((next) =>
  15.         {
  16.             return async c =>
  17.             {
  18.                 await middleware(c, () => next(c));
  19.             };
  20.         });
  21.     }
  22.     public void Use(Func<HttpContext, RequestDelegate, Task> middleware)
  23.     {
  24.         _components.Add((next) =>
  25.         {
  26.             return async c =>
  27.             {
  28.                 await middleware(c, next);
  29.             };
  30.         });
  31.     }
  32.     public void Run(RequestDelegate handler)
  33.     {
  34.         _components.Add((next) =>
  35.         {
  36.             return async c =>
  37.             {
  38.                 await handler(c);
  39.             };
  40.         });
  41.     }
  42.     //构建管道
  43.     public RequestDelegate Build()
  44.     {
  45.         RequestDelegate app = c =>
  46.         {
  47.             throw new InvalidOperationException("无效的管道");
  48.         };
  49.         for (int i = _components.Count - 1; i > -1; i--)
  50.         {
  51.             app = _components[i](app);
  52.         }
  53.         return app;
  54.     }
  55. }
复制代码
接口方式

2.通过接口构建管道
有点类型动态代理,动态代理是通过Invocation进行反射,而下面的方式是通过接口的方式。反射更加灵活,性能不行。
  1. public interface IChain
  2. {
  3.     Task NextAsync();
  4. }
  5. public class FilterChain : IChain
  6. {
  7.     private readonly IFilter _filter;
  8.     private readonly HttpContext _context;
  9.     private readonly IChain _next;
  10.     public FilterChain(IFilter filter, HttpContext context, IChain next)
  11.     {
  12.         _filter = filter;
  13.         _context = context;
  14.         _next = next;
  15.     }
  16.     public async Task NextAsync()
  17.     {
  18.         await _filter.InvokeAsync(_context, _next);
  19.     }
  20. }
  21. public class ServletChain : IChain
  22. {
  23.     private readonly IServlet _servlet;
  24.     private readonly HttpContext _context;
  25.     public ServletChain(IServlet servlet, HttpContext context)
  26.     {
  27.         _servlet = servlet;
  28.         _context = context;
  29.     }
  30.     public async Task NextAsync()
  31.     {
  32.         await _servlet.DoPostAsync(_context);
  33.     }
  34. }
  35. public interface IFilter
  36. {
  37.     Task InvokeAsync(HttpContext context, IChain chain);
  38. }
  39. public class Filter1 : IFilter
  40. {
  41.     public async Task InvokeAsync(HttpContext context, IChain chain)
  42.     {
  43.         Console.WriteLine("身份认证开始");
  44.         await chain.NextAsync();
  45.         Console.WriteLine("身份认证结束");
  46.     }
  47. }
  48. public class Filter2 : IFilter
  49. {
  50.     public async Task InvokeAsync(HttpContext context, IChain chain)
  51.     {
  52.         Console.WriteLine("授权认证开始");
  53.         await chain.NextAsync();
  54.         Console.WriteLine("授权认证结束");
  55.     }
  56. }
  57. public interface IServlet
  58. {
  59.     Task DoPostAsync(HttpContext context);
  60. }
  61. public class HelloServlet : IServlet
  62. {
  63.     public Task DoPostAsync(HttpContext context)
  64.     {
  65.         Console.WriteLine("Hello World");
  66.         return Task.CompletedTask;
  67.     }
  68. }
  69. public class WebHost
  70. {
  71.     private readonly List<IFilter> _filters = new List<IFilter>();
  72.     public void AddFilter(IFilter filter)
  73.     {
  74.         _filters.Add(filter);
  75.     }
  76.     public void Exeucte(HttpContext context, IServlet servlet)
  77.     {
  78.         //自行处理filter为空的情况,就是直接执行serlvet就好了
  79.         var stack = new Stack<IFilter>(_filters);
  80.         var filter = stack.Pop();
  81.         var chain = GetFilterChain(context, servlet,stack);
  82.         filter.InvokeAsync(context, chain);
  83.     }
  84.     private IChain GetFilterChain(HttpContext context, IServlet servlet, Stack<IFilter> filters)
  85.     {
  86.         if (filters.Any())
  87.         {
  88.             var filter = filters.Pop();
  89.             var chain = GetFilterChain(context, servlet, filters);
  90.             return new FilterChain(filter, context, chain);
  91.         }
  92.         else
  93.         {
  94.             return new ServletChain(servlet, context);
  95.         }
  96.     }
  97. }
复制代码
AOP总结

1.代理分为静态代理和动态代理,静态代理需要自己编写代理类,动态代理由框架生成代理类。
2.代理和管道都需要通过接口(委托)进行链接,串联,形成链式调用。
3.动态代理慎用,因为涉及到反射技术,而且对异步支持不友好。
4.静态代理常用于加强已有类型,比如接口要求一个IList,我们已经拥有了一个list实列,我们需要在在list.Add方法时打印日志,此时我们可以不改变原有的list,通过静态代理实现IList接口来进行对原有的list加强。这个方法在更改框架的时候很有用。我们可以对原有的HttpContext,进行加强。

来源:https://www.cnblogs.com/chaeyeon/archive/2023/02/14/17119566.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具