aspnetcore中aop的实现

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

下面介绍三种用过的。

 

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

首先新建一个aspnetcore项目

aspnetcore中aop的实现

 

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

public interface IWarService     {         string WipeOut();         IWarService Proxy(IWarService warService);     }    public class WarService : IWarService     {         public IWarService Proxy(IWarService warService)         {             return WarDispatch<IWarService>.Create(warService);         }          public string WipeOut()         {             return "us is over";         }     }

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

public class WarDispatch<T> : DispatchProxy where T : class     {         private T Target { get; set; }         public static T Create<T>(T target) where T : class         {             var proxy = Create<T, WarDispatch<T>>() as WarDispatch<T>;             proxy.Target = target;             return proxy as T;         }          protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)         {             Before().Wait();             var result = targetMethod.Invoke(Target, args);             After().Wait();             return result;         }          Task Before()         {             return Task.CompletedTask;         }          Task After()         {             return Task.CompletedTask;         }     }

实现代码也相当简单

[ApiController]     [Route("[controller]")]     public class RescueEarthController : ControllerBase     {         private IWarService _warService;                  public RescueEarthController(IWarService warService)         {             _warService = warService;         }          [HttpGet(Name = "AnnihilateHegemony")]         public string AnnihilateHegemony()         {             var proxy = _warService.Proxy(_warService); //代理             return proxy.WipeOut();         }          [HttpGet("two")]         public string AnnihilateHegemonyTwo()         {             return _warService.WipeOut();         }     }

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

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

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

 

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

首先引用aspnetcore.extensions.dependencyinjection包

aspnetcore中aop的实现

在program中使用动态代码

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

内存的缓存代理

 public class CacheDeleteInterceptorAttribute:AbstractInterceptorAttribute     {         private readonly Type[] _types;         private readonly string[] _methods;         public CacheDeleteInterceptorAttribute(Type[] types, string[] methods)         {             if (types.Length != methods.Length)             {                 throw new Exception("Types必须跟Methods数量一致");             }             _types = types;             _methods = methods;         }          public override async Task Invoke(AspectContext context, AspectDelegate next)         {             var cache = context.ServiceProvider.GetService<MemoryCache>();             await next(context);             for (int i = 0; i < _types.Length; i++)             {                 var type = _types[i];                 var method = _methods[i];                 string key = "Methods:" + type.FullName + "." + method;                 cache.Remove(key);             }         }     }

 public class CacheInterceptorAttribute : AbstractInterceptorAttribute     {         public override async Task Invoke(AspectContext context, AspectDelegate next)         {             bool isAsync = context.IsAsync();             var methodReturnType = context.GetReturnParameter().Type;             if(methodReturnType==typeof(void)|| methodReturnType==typeof(Task) || methodReturnType == typeof(ValueTask))             {                 await next(context);                 return;             }             var returnType = methodReturnType;             if (isAsync)             {                 returnType = returnType.GenericTypeArguments.FirstOrDefault();             }             //string param = GetParaName(context.Parameters); //获取方法的参数名,             string key = $"Methods:{context.ImplementationMethod.DeclaringType.FullName}.{context.ImplementationMethod.Name}";//获取方法名称,也就是缓存key值             var cache = context.ServiceProvider.GetService<MemoryCache>(); //可以使用自定义的redis或者其他缓存             if (cache.Get(key) != null)             {                 //反射获取缓存值                 var value = typeof(MemoryCache).GetMethod("MemoryCache.Get").MakeGenericMethod(returnType).Invoke(cache, new[] {                     key                     //, param                  });                 if (isAsync)                 {                      //判断是Task还是ValueTask                     if (methodReturnType == typeof(Task<>).MakeGenericType(returnType))                     {                         //反射获取Task<>类型的返回值,相当于Task.FromResult(value)                         context.ReturnValue = typeof(Task).GetMethod(nameof(Task.FromResult)).MakeGenericMethod(returnType).Invoke(null, new[] { value });                     }                     else if (methodReturnType == typeof(ValueTask<>).MakeGenericType(returnType))                     {                         //反射构建ValueTask<>类型的返回值,相当于new ValueTask(value)                         context.ReturnValue = Activator.CreateInstance(typeof(ValueTask<>).MakeGenericType(returnType), value);                     }                 }                 else                 {                     context.ReturnValue = value;                 }                 return;             }             await next(context);             object returnValue;             if (isAsync)             {                 returnValue = await context.UnwrapAsyncReturnValue();                 //反射获取异步结果的值,相当于(context.ReturnValue as Task<>).Result                 //returnValue = typeof(Task<>).MakeGenericType(returnType).GetProperty(nameof(Task<object>.Result)).GetValue(context.ReturnValue);              }             else             {                 returnValue = context.ReturnValue;             }             cache.Set(key                 //, param                 , returnValue);             if(ExpireSeconds > 0)             {                 cache.Set(key, TimeSpan.FromSeconds(ExpireSeconds));//设置key的过期时间             }         }          //private string GetParaName(object[] parameters)         //{         //    throw new NotImplementedException();         //}          /// <summary>         /// 缓存秒数         /// </summary>         public int ExpireSeconds { get; set; }     }

dbcontext的代理

public class TransactionInterceptorAttribute : AbstractInterceptorAttribute     {         //public override async Task Invoke(AspectContext context, AspectDelegate next)         //{         //    var dbcontext = context.ServiceProvider.GetService<CommonDbContext>();         //    if (dbcontext.Database.CurrentTransaction != null)         //    {         //        await dbcontext.Database.BeginTransactionAsync();         //        try         //        {         //            await next(context);         //            await dbcontext.Database.CommitTransactionAsync();         //        }catch(Exception ex)         //        {         //           await dbcontext.Database.RollbackTransactionAsync();         //            throw ex;         //        }         //    }         //    else         //    {         //        await next(context);         //    }         //}//一个context          public override async Task Invoke(AspectContext context, AspectDelegate next)         {             var dbcontext = context.ServiceProvider.GetService<CommonDbContext>();             var dbcontextNext = context.ServiceProvider.GetService<NextDbContext>();             var transactionManager = dbcontext.Database.GetService<IDbContextTransactionManager>();             var transaction = await transactionManager.BeginTransactionAsync();              if (transaction != null)             {                 await dbcontext.Database.BeginTransactionAsync();                 try                 {                     await next(context);                     await transaction.CommitAsync();                 }                 catch (Exception ex)                 {                     await transaction.RollbackAsync();                     throw ex;                 }             }             else             {                 await next(context);             }         }//多个context     }

 public class CommonDbContext:DbContext     {         public CommonDbContext(DbContextOptions<CommonDbContext> options):base(options)         {          }     }      public class NextDbContext : DbContext     {         public NextDbContext(DbContextOptions<CommonDbContext> options) : base(options)         {          }     }

使用就是这么简单

 public class TestOperatorDbBusiness     {         [TransactionInterceptor]         public async ValueTask Add()         {             //TODO事务操作         }     }

 

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

上面代码的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,这里面的拦截器也非常多,还有好多等待发掘。

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

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

 

发表评论

评论已关闭。

相关文章