暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

FluentAspects -- 基于 Fluent API 的 Aop

amazingdotnet 2020-05-02
175

FluentAspects -- 基于 Fluent API 的 Aop

Intro

上次我们做了一个简单的 AOP 实现示例,但是实现起来主要是基于 Attribute
来做的,对于代码的侵入性太强,于是尝试实现基于 Fluent API 的方式来做 AOP 。

抽象 InterceptorResolver

原来获取方法执行的 Interceptor 是通过 Attribute
来获取的,现在我们只需要将获取 Interceptor 的逻辑抽象出来就可以实现不必依赖于 Attribute

方法执行上下文定义:

  1. public interface IInvocation

  2. {

  3. public MethodInfo ProxyMethod { get; }


  4. public object ProxyTarget { get; }


  5. public MethodInfo Method { get; }


  6. public object Target { get; }


  7. public object[] Arguments { get; }


  8. Type[] GenericArguments { get; }


  9. public object ReturnValue { get; set; }

  10. }

方法拦截器 Interceptor
接口定义:

  1. public interface IInterceptor

  2. {

  3. Task Invoke(IInvocation invocation, Func<Task> next);

  4. }

自定义 Interceptor 只需要继承这个接口实现相应的逻辑就好了

获取 IInterceptorResolver
接口定义:

  1. public interface IInterceptorResolver

  2. {

  3. IReadOnlyCollection<IInterceptor> ResolveInterceptors(IInvocation invocation);

  4. }

原来基于 Attribute
获取 Interceptor 的方式可以实现一个 AttributeInterceptorResolver

想要基于 Fluent API 来获取 Interceptor ,只需要实现基于 Fluent API 的 InterceptorResolver
就可以了,具体的实现可以参考 FluentConfigInterceptorResolver

示例预览

测试服务定义:

  1. public interface ISvc1

  2. {

  3. void Invoke();

  4. }


  5. public interface ISvc2

  6. {

  7. void Invoke();

  8. }


  9. public class Svc2 : ISvc2

  10. {

  11. public void Invoke()

  12. {

  13. Console.WriteLine($"invoking in {GetType().Name} ...");

  14. }


  15. public void Invoke2()

  16. {

  17. Console.WriteLine($"invoking in {GetType().Name} ...");

  18. }

  19. }


  20. public class Svc3

  21. {

  22. public virtual void Invoke()

  23. {

  24. Console.WriteLine($"invoking in {GetType().Name} ...");

  25. }

  26. }


  27. public class Svc4

  28. {

  29. public virtual void Invoke()

  30. {

  31. Console.WriteLine($"invoking in {GetType().Name} ...");

  32. }


  33. public void Invoke2()

  34. {

  35. Console.WriteLine($"invoking2 in {GetType().Name} ...");

  36. }


  37. public virtual void Invoke3()

  38. {

  39. Console.WriteLine($"invoking3 in {GetType().Name} ...");

  40. }

  41. }

测试 Interceptor

  1. internal class LogInterceptor : IInterceptor

  2. {

  3. public async Task Invoke(IInvocation invocation, Func<Task> next)

  4. {

  5. Console.WriteLine($"invoke {invocation.ProxyMethod} in {GetType().Name} begin");

  6. await next();

  7. Console.WriteLine($"invoke {invocation.ProxyMethod} in {GetType().Name} end");

  8. }

  9. }

测试代码:

  1. public static void Main(string[] args)

  2. {

  3. var services = new ServiceCollection();

  4. services.AddFluentAspects(options =>

  5. {

  6. // 为所有拦截的方法添加拦截器

  7. options.InterceptAll()

  8. .With<LogInterceptor>()

  9. ;

  10. // 对 Svc3 类型禁用拦截器

  11. options.NoInterceptType<Svc3>();

  12. // Svc4 类型的 Invoke3() 方法禁用拦截器

  13. options.NoInterceptMethod<Svc4>(s => s.Invoke3());

  14. });

  15. services.AddTransientProxy<Svc4>();

  16. var serviceProvider = services.BuildServiceProvider();

  17. var proxyFactory = serviceProvider.GetRequiredService<IProxyFactory>();


  18. var svc1 = proxyFactory.CreateProxy<ISvc1>();

  19. svc1.Invoke();

  20. Console.WriteLine();


  21. var svc2 = proxyFactory.CreateProxy<ISvc2, Svc2>();

  22. svc2.Invoke();

  23. Console.WriteLine();


  24. var svc3 = proxyFactory.CreateProxy<Svc3>();

  25. svc3.Invoke();

  26. Console.WriteLine();


  27. var svc4 = proxyFactory.CreateProxyWithTarget<ISvc2, Svc2>(new Svc2());

  28. svc4.Invoke();

  29. Console.WriteLine();


  30. // 直接从注册的服务中获取

  31. var svc5 = serviceProvider.GetRequiredService<Svc4>();

  32. svc5.Invoke();

  33. Console.WriteLine();

  34. svc5.Invoke2();

  35. Console.WriteLine();

  36. svc5.Invoke3();

  37. Console.WriteLine();


  38. Console.WriteLine("finished");

  39. Console.ReadLine();

  40. }

输出结果预览:

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


文章转载自amazingdotnet,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论