【代码设计】C# 实现 AOP 面向切面编程
簡單記錄一下對AOP的認識,正文為3個部分
一、AOP由來
二、用DispatchProxy動態代理實現AOP
三、通過特性標記,處理多種不同執行前、執行后的邏輯編排
一、AOP 由來
IUserHelper userHelper = new CommonUserHelper();
// 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();
}
}
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的封裝(可通過Nuget管理下載),
通過實現 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);
// 對于 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);
};
}
}
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();
}
============================================================
具體的AOP實現上需要考慮的問題多如牛毛,此處僅做簡單的思路介紹。
以上主要參考自 B站 朝夕教育 2022 .Net Core AOP實現。
總結
以上是生活随笔為你收集整理的【代码设计】C# 实现 AOP 面向切面编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java多线程系列(1)
- 下一篇: 进化吧!我的C++!!