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, Funcnext); }
自定义 Interceptor 只需要继承这个接口实现相应的逻辑就好了
获取 IInterceptorResolver 接口定义:
public interface IInterceptorResolver { IReadOnlyCollectionResolveInterceptors(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, Funcnext) { 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() ; // 对 Svc3 类型禁用拦截器 options.NoInterceptType(); // Svc4 类型的 Invoke3() 方法禁用拦截器 options.NoInterceptMethod(s => s.Invoke3()); }); services.AddTransientProxy(); var serviceProvider = services.BuildServiceProvider(); var proxyFactory = serviceProvider.GetRequiredService(); var svc1 = proxyFactory.CreateProxy(); svc1.Invoke(); Console.WriteLine(); var svc2 = proxyFactory.CreateProxy(); svc2.Invoke(); Console.WriteLine(); var svc3 = proxyFactory.CreateProxy(); svc3.Invoke(); Console.WriteLine(); var svc4 = proxyFactory.CreateProxyWithTarget(new Svc2()); svc4.Invoke(); Console.WriteLine(); // 直接从注册的服务中获取 var svc5 = serviceProvider.GetRequiredService(); 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