aaspnetcore开发框架中实现aop不仅仅在业务上,在代码的优雅简洁和架构的稳定上都有着至关重要。

下面介绍三种用过的。

第一种通过System.Reflection的DispatchProxy类来实现

首先新建一个aspnetcore项目

针对业务代码WarService加了一个代理的方法

  1. public interface IWarService
  2. {
  3. string WipeOut();
  4. IWarService Proxy(IWarService warService);
  5. }
  6.  
  7. public class WarService : IWarService
  8. {
  9. public IWarService Proxy(IWarService warService)
  10. {
  11. return WarDispatch<IWarService>.Create(warService);
  12. }
  13.  
  14. public string WipeOut()
  15. {
  16. return "us is over";
  17. }
  18. }

具体的WarDispatch就是核心代码了,继承自DispatchProxy。这里的before和after的实现就是针对实现了代码的service提前挖坑。

  1. public class WarDispatch<T> : DispatchProxy where T : class
  2. {
  3. private T Target { get; set; }
  4. public static T Create<T>(T target) where T : class
  5. {
  6. var proxy = Create<T, WarDispatch<T>>() as WarDispatch<T>;
  7. proxy.Target = target;
  8. return proxy as T;
  9. }
  10.  
  11. protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)
  12. {
  13. Before().Wait();
  14. var result = targetMethod.Invoke(Target, args);
  15. After().Wait();
  16. return result;
  17. }
  18.  
  19. Task Before()
  20. {
  21. return Task.CompletedTask;
  22. }
  23.  
  24. Task After()
  25. {
  26. return Task.CompletedTask;
  27. }
  28. }

实现代码也相当简单

  1. [ApiController]
  2. [Route("[controller]")]
  3. public class RescueEarthController : ControllerBase
  4. {
  5. private IWarService _warService;
  6.  
  7. public RescueEarthController(IWarService warService)
  8. {
  9. _warService = warService;
  10. }
  11.  
  12. [HttpGet(Name = "AnnihilateHegemony")]
  13. public string AnnihilateHegemony()
  14. {
  15. var proxy = _warService.Proxy(_warService); //代理
  16. return proxy.WipeOut();
  17. }
  18.  
  19. [HttpGet("two")]
  20. public string AnnihilateHegemonyTwo()
  21. {
  22. return _warService.WipeOut();
  23. }
  24. }

当然不要忘了注入下服务类

  1. builder.Services.AddScoped<IWarService, WarService>();

上面的方式是我自己想出来的,具体到项目中需要改进的地方应该还有很多,但是足够简单,功能也比较单一。

下面简单介绍下AspectCore.DynamicProxy现成组件的代理使用。

首先引用aspnetcore.extensions.dependencyinjection包

在program中使用动态代码

  1. builder.Host.UseServiceProviderFactory(new DynamicProxyServiceProviderFactory());
  2. builder.Services.ConfigureDynamicProxy(o =>{
  3. //添加aop的配置
  4. //该项目用attribute所以无需配置
  5.  
  6. });

内存的缓存代理

  1. public class CacheDeleteInterceptorAttribute:AbstractInterceptorAttribute
  2. {
  3. private readonly Type[] _types;
  4. private readonly string[] _methods;
  5. public CacheDeleteInterceptorAttribute(Type[] types, string[] methods)
  6. {
  7. if (types.Length != methods.Length)
  8. {
  9. throw new Exception("Types必须跟Methods数量一致");
  10. }
  11. _types = types;
  12. _methods = methods;
  13. }
  14.  
  15. public override async Task Invoke(AspectContext context, AspectDelegate next)
  16. {
  17. var cache = context.ServiceProvider.GetService<MemoryCache>();
  18. await next(context);
  19. for (int i = 0; i < _types.Length; i++)
  20. {
  21. var type = _types[i];
  22. var method = _methods[i];
  23. string key = "Methods:" + type.FullName + "." + method;
  24. cache.Remove(key);
  25. }
  26. }
  27. }
  1. public class CacheInterceptorAttribute : AbstractInterceptorAttribute
  2. {
  3. public override async Task Invoke(AspectContext context, AspectDelegate next)
  4. {
  5. bool isAsync = context.IsAsync();
  6. var methodReturnType = context.GetReturnParameter().Type;
  7. if(methodReturnType==typeof(void)|| methodReturnType==typeof(Task) || methodReturnType == typeof(ValueTask))
  8. {
  9. await next(context);
  10. return;
  11. }
  12. var returnType = methodReturnType;
  13. if (isAsync)
  14. {
  15. returnType = returnType.GenericTypeArguments.FirstOrDefault();
  16. }
  17. //string param = GetParaName(context.Parameters); //获取方法的参数名,
  18. string key = $"Methods:{context.ImplementationMethod.DeclaringType.FullName}.{context.ImplementationMethod.Name}";//获取方法名称,也就是缓存key值
  19. var cache = context.ServiceProvider.GetService<MemoryCache>(); //可以使用自定义的redis或者其他缓存
  20. if (cache.Get(key) != null)
  21. {
  22. //反射获取缓存值
  23. var value = typeof(MemoryCache).GetMethod("MemoryCache.Get").MakeGenericMethod(returnType).Invoke(cache, new[] {
  24. key
  25. //, param
  26. });
  27. if (isAsync)
  28. {
  29.  
  30. //判断是Task还是ValueTask
  31. if (methodReturnType == typeof(Task<>).MakeGenericType(returnType))
  32. {
  33. //反射获取Task<>类型的返回值,相当于Task.FromResult(value)
  34. context.ReturnValue = typeof(Task).GetMethod(nameof(Task.FromResult)).MakeGenericMethod(returnType).Invoke(null, new[] { value });
  35. }
  36. else if (methodReturnType == typeof(ValueTask<>).MakeGenericType(returnType))
  37. {
  38. //反射构建ValueTask<>类型的返回值,相当于new ValueTask(value)
  39. context.ReturnValue = Activator.CreateInstance(typeof(ValueTask<>).MakeGenericType(returnType), value);
  40. }
  41. }
  42. else
  43. {
  44. context.ReturnValue = value;
  45. }
  46. return;
  47. }
  48. await next(context);
  49. object returnValue;
  50. if (isAsync)
  51. {
  52. returnValue = await context.UnwrapAsyncReturnValue();
  53. //反射获取异步结果的值,相当于(context.ReturnValue as Task<>).Result
  54. //returnValue = typeof(Task<>).MakeGenericType(returnType).GetProperty(nameof(Task<object>.Result)).GetValue(context.ReturnValue);
  55.  
  56. }
  57. else
  58. {
  59. returnValue = context.ReturnValue;
  60. }
  61. cache.Set(key
  62. //, param
  63. , returnValue);
  64. if(ExpireSeconds > 0)
  65. {
  66. cache.Set(key, TimeSpan.FromSeconds(ExpireSeconds));//设置key的过期时间
  67. }
  68. }
  69.  
  70. //private string GetParaName(object[] parameters)
  71. //{
  72. // throw new NotImplementedException();
  73. //}
  74.  
  75. /// <summary>
  76. /// 缓存秒数
  77. /// </summary>
  78. public int ExpireSeconds { get; set; }
  79. }

dbcontext的代理

  1. public class TransactionInterceptorAttribute : AbstractInterceptorAttribute
  2. {
  3. //public override async Task Invoke(AspectContext context, AspectDelegate next)
  4. //{
  5. // var dbcontext = context.ServiceProvider.GetService<CommonDbContext>();
  6. // if (dbcontext.Database.CurrentTransaction != null)
  7. // {
  8. // await dbcontext.Database.BeginTransactionAsync();
  9. // try
  10. // {
  11. // await next(context);
  12. // await dbcontext.Database.CommitTransactionAsync();
  13. // }catch(Exception ex)
  14. // {
  15. // await dbcontext.Database.RollbackTransactionAsync();
  16. // throw ex;
  17. // }
  18. // }
  19. // else
  20. // {
  21. // await next(context);
  22. // }
  23. //}//一个context
  24.  
  25. public override async Task Invoke(AspectContext context, AspectDelegate next)
  26. {
  27. var dbcontext = context.ServiceProvider.GetService<CommonDbContext>();
  28. var dbcontextNext = context.ServiceProvider.GetService<NextDbContext>();
  29. var transactionManager = dbcontext.Database.GetService<IDbContextTransactionManager>();
  30. var transaction = await transactionManager.BeginTransactionAsync();
  31.  
  32. if (transaction != null)
  33. {
  34. await dbcontext.Database.BeginTransactionAsync();
  35. try
  36. {
  37. await next(context);
  38. await transaction.CommitAsync();
  39. }
  40. catch (Exception ex)
  41. {
  42. await transaction.RollbackAsync();
  43. throw ex;
  44. }
  45. }
  46. else
  47. {
  48. await next(context);
  49. }
  50. }//多个context
  51. }
  1. public class CommonDbContext:DbContext
  2. {
  3. public CommonDbContext(DbContextOptions<CommonDbContext> options):base(options)
  4. {
  5.  
  6. }
  7. }
  8.  
  9. public class NextDbContext : DbContext
  10. {
  11. public NextDbContext(DbContextOptions<CommonDbContext> options) : base(options)
  12. {
  13.  
  14. }
  15. }

使用就是这么简单

  1. public class TestOperatorDbBusiness
  2. {
  3. [TransactionInterceptor]
  4. public async ValueTask Add()
  5. {
  6. //TODO事务操作
  7. }
  8. }

上面的代理组件功能非常多,项目中需要自己去研究更多更全的用法。

上面代码的demo

exercisebook/AOP at main · liuzhixin405/exercisebook (github.com)

还有Castle.DynamicProxy,这个比较复杂一点。具体用法给个实例demo

exercisebook/AspNetCoreAOP at main · liuzhixin405/exercisebook (github.com)

总结:

一个aspnetcore中需要用到aop的地方非常多,框架自带的中间件,filter过滤器,efcore自带Interceptor都可以拿来用。

中间件例如mediator,这里面的拦截器也非常多,还有好多等待发掘。

当然自己也可以定义一些简单的中间层来做拦截。

相信多了解 在框架中有需要用的地方会事半功倍。

aspnetcore中aop的实现的更多相关文章

  1. AspNetCore 基于AOP实现Polly的使用

    前言   说起AOP,其实我们在做MVC/API 的时候应该没少接触,比如说各种的Fitter 就是典型的AOP了. 本来在使用Polly的时候我最初的打算是使用过滤器来实现的,后来发现实现起来相当的 ...

  2. Spring中AOP原理,源码学习笔记

    一.AOP(面向切面编程):通过预编译和运行期动态代理的方式在不改变代码的情况下给程序动态的添加一些功能.利用AOP可以对应用程序的各个部分进行隔离,在Spring中AOP主要用来分离业务逻辑和系统级 ...

  3. Spring中AOP简介与切面编程的使用

    Spring中AOP简介与使用 什么是AOP? Aspect Oriented Programming(AOP),多译作 "面向切面编程",也就是说,对一段程序,从侧面插入,进行操 ...

  4. 在AspNetCore 中 使用Redis实现分布式缓存

    AspNetCore 使用Redis实现分布式缓存 上一篇讲到了,Core的内置缓存:IMemoryCache,以及缓存的基础概念.本篇会进行一些概念上的补充. 本篇我们记录的内容是怎么在Core中使 ...

  5. AspNetCore中使用Ocelot之 IdentityServer4(1)

    AspNetCore中使用Ocelot之 IdentityServer4(1) 前言: OceLot网关是基于AspNetCore 产生的可扩展的高性能的企业级Api网关,目前已经基于2.0 升级版本 ...

  6. 第四节:MVC中AOP思想的体现(四种过滤器)并结合项目案例说明过滤器的实际用法

    一. 简介 MVC中的过滤器可以说是MVC框架中的一种灵魂所在,它是MVC框架中AOP思想的具体体现,所以它以面向切面的形式无侵入式的作用于代码的业务逻辑,与业务逻辑代码分离,一经推出,广受开发者的喜 ...

  7. 框架源码系列十:Spring AOP(AOP的核心概念回顾、Spring中AOP的用法、Spring AOP 源码学习)

    一.AOP的核心概念回顾 https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/core.html#a ...

  8. Spring中AOP实现

    1.什么是SpringAOP 什么是aop:Aspect Oriented Programming的缩写,面向切面编程,通过预编译和动态代理实现程序功能的 统一维护的一种技术 主要功能:日志记录,性能 ...

  9. Spring 中aop切面注解实现

    spring中aop的注解实现方式简单实例   上篇中我们讲到spring的xml实现,这里我们讲讲使用注解如何实现aop呢.前面已经讲过aop的简单理解了,这里就不在赘述了. 注解方式实现aop我们 ...

  10. 在ASPNETCORE中获得所有Action

    在ASPNETCORE中获得所有Action 本文旨在记录自己在aspnetcore工作中需要获取所有Action,在查询了资料后进行了几种方法的记录.后期有发现其它方式再进行追加. 一.通过 反射 ...

随机推荐

  1. python 读取ini文件内容

    1 import configparser 2 cfgini = "D:\\123.ini" 3 conf = configparser.ConfigParser() 4 conf ...

  2. C#——》创建Windows服务,发布并调试Windows服务

    一,创建一个windows服务项目.  二,双击Service1.cs进入设计界面,在空白处右键单击选择添加安装程序,如下图所示. 三,添加安装程序后,会进入如下图界面,生成两个组件:serviceP ...

  3. mac 安装 nginx 流程,并解决前端跨域问题

    mac 安装 nginx 流程 首先mac安装brew包管理工具: /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN ...

  4. jetson nano 2gb相关问题

    1.create_ap不能根据address设置带设备号的wifi热点 sudo nohup create_ap wlan0 eth0 ZL_Jetson_WIFI-$(sudo cat /sys/c ...

  5. Git Peer reports incompatible or unsupported protocol version

    今天用git克隆一个项目的时候出现标题中的错误 fatal: unable to access 'xxx.git/': Peer reports incompatible or unsupported ...

  6. Python爬虫之Scrapy框架爬虫实战

    Python爬虫中Scrapy框架应用非常广泛,经常被人用于属于挖掘.检测以及自动化测试类项目,为啥说Scrapy框架作为半成品我们又该如何利用好呢 ?下面的实战案例值得大家看看. 目录: 1.Scr ...

  7. 阿里云Linux服务器安装Maven实战教程

    下载地址 https://maven.apache.org/download.cgi 文件上传 把下载的文件上传到阿里云服务器 /usr/local/software 的目录(使用工具) window ...

  8. 如何简单使用Git

    Git基本功能 Git基本功能 在具体介绍Git能做什么之前,先来了解下Git里的四个角色: workspace: 本地的工作空间. index:缓存区域,临时保存本地改动. local reposi ...

  9. 1js 高级

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. OSIDP-文件管理-12(end)

    概述 文件特性:可长期存储:可在进程间共享:有特定结构. 文件系统提供对文件操作的功能接口:创建.删除.打开.关闭.读和写. 域(field):基本数据单元,一个域包含一个值. 记录(record): ...