FluentAspects -- 基于 Fluent API 的 Aop
FluentAspects -- 基于 Fluent API 的 Aop
Intro
上次我們做了一個簡單的 AOP 實現示例,但是實現起來主要是基于 Attribute 來做的,對于代碼的侵入性太強,于是嘗試實現基于 Fluent API 的方式來做 AOP 。
抽象 InterceptorResolver
原來獲取方法執行的 Interceptor 是通過 Attribute 來獲取的,現在我們只需要將獲取 Interceptor 的邏輯抽象出來就可以實現不必依賴于 Attribute 了
方法執行上下文定義:
public interface IInvocation {public MethodInfo ProxyMethod { get; }public object ProxyTarget { get; }public MethodInfo Method { get; }public object Target { get; }public object[] Arguments { get; }Type[] GenericArguments { get; }public object ReturnValue { get; set; } }方法攔截器 Interceptor 接口定義:
public interface IInterceptor {Task Invoke(IInvocation invocation, Func<Task> next); }自定義 Interceptor 只需要繼承這個接口實現相應的邏輯就好了
獲取 IInterceptorResolver 接口定義:
public interface IInterceptorResolver {IReadOnlyCollection<IInterceptor> ResolveInterceptors(IInvocation invocation); }原來基于 Attribute 獲取 Interceptor 的方式可以實現一個 AttributeInterceptorResolver
想要基于 Fluent API 來獲取 Interceptor ,只需要實現基于 Fluent API 的 InterceptorResolver 就可以了,具體的實現可以參考 FluentConfigInterceptorResolver
示例預覽
測試服務定義:
public interface ISvc1 {void Invoke(); } public interface ISvc2 {void Invoke(); } public class Svc2 : ISvc2 {public void Invoke(){Console.WriteLine($"invoking in {GetType().Name} ...");}public void Invoke2(){Console.WriteLine($"invoking in {GetType().Name} ...");} } public class Svc3 {public virtual void Invoke(){Console.WriteLine($"invoking in {GetType().Name} ...");} } public class Svc4 {public virtual void Invoke(){Console.WriteLine($"invoking in {GetType().Name} ...");}public void Invoke2(){Console.WriteLine($"invoking2 in {GetType().Name} ...");}public virtual void Invoke3(){Console.WriteLine($"invoking3 in {GetType().Name} ...");} }測試 Interceptor
internal class LogInterceptor : IInterceptor {public async Task Invoke(IInvocation invocation, Func<Task> next){Console.WriteLine($"invoke {invocation.ProxyMethod} in {GetType().Name} begin");await next();Console.WriteLine($"invoke {invocation.ProxyMethod} in {GetType().Name} end");} }測試代碼:
public static void Main(string[] args) {var services = new ServiceCollection();services.AddFluentAspects(options =>{// 為所有攔截的方法添加攔截器options.InterceptAll().With<LogInterceptor>();// 對 Svc3 類型禁用攔截器options.NoInterceptType<Svc3>();// Svc4 類型的 Invoke3() 方法禁用攔截器options.NoInterceptMethod<Svc4>(s => s.Invoke3());});services.AddTransientProxy<Svc4>();var serviceProvider = services.BuildServiceProvider();var proxyFactory = serviceProvider.GetRequiredService<IProxyFactory>();var svc1 = proxyFactory.CreateProxy<ISvc1>();svc1.Invoke();Console.WriteLine();var svc2 = proxyFactory.CreateProxy<ISvc2, Svc2>();svc2.Invoke();Console.WriteLine();var svc3 = proxyFactory.CreateProxy<Svc3>();svc3.Invoke();Console.WriteLine();var svc4 = proxyFactory.CreateProxyWithTarget<ISvc2, Svc2>(new Svc2());svc4.Invoke();Console.WriteLine();// 直接從注冊的服務中獲取var svc5 = serviceProvider.GetRequiredService<Svc4>();svc5.Invoke();Console.WriteLine();svc5.Invoke2();Console.WriteLine();svc5.Invoke3();Console.WriteLine();Console.WriteLine("finished");Console.ReadLine(); }輸出結果預覽:
More
最近十幾天的時間一直在搞這個,相比之前寫的示例,真正實現一個完整的 AOP 框架還是要做比較多的事情的,之前的 AOP 示例,沒有考慮泛型,也沒有什么設計,所以前面的示例只能算是一個小玩具。
在實現的過程中,參考了很多 AspectCore 的代碼,有一些代碼甚至是直接從 AspectCore 里抄過來的。
推薦大家有機會研究學習一下檸檬大佬的 AspectCore 的源碼,這個 AOP 框架的代碼組織,代碼細節都挺不錯的。
AspectCore 源碼地址:https://github.com/dotnetcore/AspectCore-Framework
Reference
https://github.com/WeihanLi/WeihanLi.Common/tree/dev/src/WeihanLi.Common/Aspect
https://github.com/WeihanLi/SamplesInPractice/blob/master/FluentAspectSample/Program.cs
https://github.com/dotnetcore/AspectCore-Framework
總結
以上是生活随笔為你收集整理的FluentAspects -- 基于 Fluent API 的 Aop的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Jenkins 中以构建 Tag 来实现
- 下一篇: 面向接口编程,你考虑过性能吗?