Asp.Net Core轻量级Aop解决方案:AspectCore

2019-05-25 20:05:03王冬梅

修改全局拦截器注册:

services.AddAspectCore(config =>
{
   config.InterceptorFactories.AddTyped<CustomInterceptorAttribute>(args: new object[] { "custom" });
});

作为服务的全局拦截器。在ConfigureServices中添加:

services.AddTransient<CustomInterceptorAttribute>(provider => new CustomInterceptorAttribute("service"));

修改全局拦截器注册:

services.AddAspectCore(config =>
{
  config.InterceptorFactories.AddServiced<CustomInterceptorAttribute>();
});

作用于特定Service或Method的全局拦截器,下面的代码演示了作用于带有Service后缀的类的全局拦截器:

services.AddAspectCore(config =>
{
  config.InterceptorFactories.AddTyped<CustomInterceptorAttribute>(method => method.DeclaringType.Name.EndsWith("Service"));
});

使用通配符的特定全局拦截器:

services.AddAspectCore(config =>
{
  config.InterceptorFactories.AddTyped<CustomInterceptorAttribute>(PredicateFactory.ForService("*Service"));
});

在AspectCore中提供NonAspectAttribute来使得Service或Method不被代理:

[NonAspect]
public interface ICustomService
{
  void Call();
}

同时支持全局忽略配置,亦支持通配符:

 services.AddAspectCore(config =>
 {
   //App1命名空间下的Service不会被代理
   config.NonAspectOptions.AddNamespace("App1");
   //最后一级为App1的命名空间下的Service不会被代理
   config.NonAspectOptions.AddNamespace("*.App1");
   //ICustomService接口不会被代理
   config.NonAspectOptions.AddService("ICustomService");
   //后缀为Service的接口和类不会被代理
   config.NonAspectOptions.AddService("*Service");
   //命名为Query的方法不会被代理
   config.NonAspectOptions.AddMethod("Query");
   //后缀为Query的方法不会被代理
   config.NonAspectOptions.AddMethod("*Query");
 });

拦截器中的依赖注入。在拦截器中支持属性注入,构造器注入和服务定位器模式。
属性注入,在拦截器中拥有public get and set权限的属性标记[AspectCore.Abstractions.FromServices](区别于Microsoft.AspNetCore.Mvc.FromServices)特性,即可自动注入该属性,如:

public class CustomInterceptorAttribute : InterceptorAttribute
{
  [AspectCore.Abstractions.FromServices]
  public ILogger<CustomInterceptorAttribute> Logger { get; set; }
  public override Task Invoke(AspectContext context, AspectDelegate next)
  {
    Logger.LogInformation("call interceptor");
    return next(context);
  }
}

构造器注入需要使拦截器作为Service,除全局拦截器外,仍可使用ServiceInterceptor使拦截器从DI中激活:

public interface ICustomService
{
  [ServiceInterceptor(typeof(CustomInterceptorAttribute))]
  void Call();
}