|
一、AOP 由来
- IUserHelper userHelper = new CommonUserHelper();<br> // commonUser.Create中存在 方法执行前、方法执行后的业务逻辑
- userHelper.Create("test0401_A");
- public interface IUserHelper
- {
- void Create(string name);
- }
- public class CommonUserHelper : IUserHelper
- {
- private void before()
- {
- Console.WriteLine("CommonUser before");
- }
- private void after()
- {
- Console.WriteLine("CommonUser after");
- }
- public void Create(string name)
- {
- before();
- Console.WriteLine($" Common User : {name} Created !");
- after();
- }
- }
- <br>
复制代码 CommonUserHelper 实现 IUserHelper 接口,假设希望在 Create方法执行前/后写入日志,那就存在这4种业务逻辑:
① 执行前写入日志,执行 Create
② 执行前写入日志,执行 Create,执行后写入日志
③ 执行 Create,执行后写入日志
④ 执行 Create
单一个写日志的需求,就能有4种实现方式,极端情况下,是可以实现 4次 Create 方法;
如果再加一个数据验证、IP验证、权限验证、异常处理、加入缓存..,那么实现的排列组合方式就更多了,
无穷尽地加实现、替换类,这显然不是我们希望的。
AOP,Aspect Oriented Programing,是一种编程思维,是对这种缺陷的补充。
二、DispatchProxy (动态代理)实现AOP
- using System.Reflection;
- namespace Cjm.AOP
- {
- public class TransformProxy
- {
- public static T GetDynamicProxy<T>(T instance)
- {
- // DispatchProxy 是system.Reflection封装的类
- // 用以创建实现接口T的代理类CustomProxy的实例
- dynamic obj = DispatchProxy.Create<T, CustomProxy<T>>();
- obj.Instance = instance;
- return (T)obj;
- }
- }
- // DispatchProxy 是抽象类,
- // 实现该类的实例,实例方法执行是会跳转到 Invoke 方法中,
- // 以此达到不破坏实际执行的具体逻辑,而又可以在另外的地方实现执行前、执行后
- public class CustomProxy<T> : DispatchProxy
- {
- public T Instance { get; set; }
- protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)
- {
- BeforeProcess();
- var relt = targetMethod?.Invoke(Instance, args);
- AfterProcess();
- return relt;
- }
- private void BeforeProcess()
- {
- Console.WriteLine($"This is BegoreProcess.");
- }
- private void AfterProcess()
- {
- Console.WriteLine($"This is AfterProcess.");
- }
- }
- }
- // Main
- IUserHelper userHelper3 = new CommonUserHelper();
- userHelper3 = TransformProxy.GetDynamicProxy(userHelper3);
- userHelper3.Create("test0401_B");
复制代码
三、通过标记特性,处理多种不同的执行前/执行后方法
此处借用Castle.Core的封装,
通过实现 StandardInterceptor以重写 执行前/执行后 逻辑的封装方式,
我们可以更加聚焦在如何处理多种 执行前/执行后 逻辑的编排上。- using Castle.DynamicProxy;
- {
- ProxyGenerator proxy = new ProxyGenerator();
- CustomInterceptor customInterceptor = new CustomInterceptor();
- IUserHelper commonUserHelper = new CommonUserHelper();
- var userHelperProxy = proxy.CreateInterfaceProxyWithTarget<IUserHelper>(commonUserHelper, customInterceptor);
- userHelperProxy.Create("TEST0401_C");
- }
复制代码- public class CustomInterceptor : StandardInterceptor
- {
- protected override void PreProceed(IInvocation invocation)
- {
- var method = invocation.Method;
- //if (method.IsDefined(typeof(LogBeforeAttribute), true))
- //{
- // Console.WriteLine("LOG : CustomInterceptor.PreProceed");
- //}
- Action<IInvocation> action = (invocation) => base.PreProceed(invocation);
- // 获取该方法的所有继承BaseAOPAttribute的特性
- var attrs = method.GetCustomAttributes<BaseAOPAttribute>(true);<br> // 对于 attrs 的排列顺序,可以在特性的实现中增加 int order 属性,在标记特性时写入排序编号
- foreach(var attr in attrs)
- {
- // 这里是俄罗斯套娃
- // 相当于 attr3.AOPAction(invocation, attr2.AOPAction(invocation, attr1.AOPAction(invocation, base.PreProceed(invocation))))
- action = attr.AOPAction(invocation, action);
- }
- action.Invoke(invocation);
- }
- protected override void PerformProceed(IInvocation invocation)
- {
- Console.WriteLine("CustomInterceptor.PerformProceed");
- base.PerformProceed(invocation);
- }
- protected override void PostProceed(IInvocation invocation)
- {
- var method = invocation.Method;
- if (method.IsDefined(typeof(LogAfterAttribute), true))
- {
- Console.WriteLine("LOG : CustomInterceptor.PostProceed");
- }
- base.PreProceed(invocation);
- }
- }
复制代码- public class LogBeforeAttribute : Attribute {}
- public class LogAfterAttribute : Attribute {}
- public class CheckIPAttribute : BaseAOPAttribute
- {
- public override Action<IInvocation> AOPAction(IInvocation invocation, Action<IInvocation> action)
- {
- return (invocation) => {
- Console.WriteLine("CheckIP ..");
- action.Invoke(invocation); <br> };
- }
- }
- public abstract class BaseAOPAttribute : Attribute
- {
- public abstract Action<IInvocation> AOPAction(IInvocation invocation, Action<IInvocation> action);
- }
复制代码 通过给方法标记特性的方式,达到切面编程的目的(不影响原有实现,而增加实现执行前/执行后的逻辑)- public interface IUserHelper
- {
- [LogBefore]
- [LogAfter]
- [CheckIP]
- void Create(string name);
- void CreateNoAttri();
- }
复制代码
来源:https://www.cnblogs.com/carmen-019/archive/2023/04/02/17280096.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
|