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 就可以了, 具体的实现可以参考
示例预览
测试服务定义:
- 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/dotnetcore/AspectCore-Framework
来源: https://www.cnblogs.com/weihanli/p/12815729.html