AOP in dotnet :AspectCore的参数拦截支持

距离上一篇AspectCore的介绍发布已经很长一段时间了,这篇文章也早该和大家见面,最近一直忙于适应新工作,并在业余时间有幸向何镇汐Savorboard农夫AlexLEWIS等几位大牛请教学习,收获颇多。另一方面,一直在对AspectCore进行重构,并把AspectCoreAspectCore Project迁移到.NET China Foundation(前身为AspNetCore文档翻译小组),由我和 DotNetCore 项目组共同维护。下面言归正传,一起来看一下AspectCore给大家带来的新特性。

AspectCore 0.1.2-release

AspectCore v0.1.2已经正式发布,相对于前一个版本,V0.1.2中除了修复若干bug外,最重要的特性就是带来了方法参数拦截器和方法参数注入的支持。

参数拦截器

我们先来看下面的方法:

public class AppService : IAppService
{
    public void Run(string[] args)
    {
        if (args == null)
        {
            throw new ArgumentNullException(nameof(args));
        }
        // todo..
    }
}

在开发中,对方法的输入参数进行非空校验是一个不错的编程习惯,可以避免意外的抛出NullReferenceException,但对于所有方法的参数都进行如上的手动验证的话,又是一个很耗费人力的事情。那么能不能只在参数上标记自定义的特性,让框架来帮助我们进行自动的参数验证呢?比如下面的代码:

public void Run([NotNull]string[] args)
{
    //todo..
}

接下来,让我们来看看AspectCore是怎么做的吧。

  1. 新建.net core的ConsoleApp项目,添加AspectCore的nuget packages:

    PM> Install-Package AspectCore.Extensions.DependencyInjection
    PM> Install-Package AspectCore.Extensions.CrossParameters
  2. 在Main方法中添加:

    public class Program
    {
        public static void Main(string[] args)
        {
            IServiceCollection services = new ServiceCollection();
            services.AddAspectCore(options =>
            {
                options.AddMethodInject();
                options.AddParameterIntercept();
            });
            services.AddTransient<IAppService, AppService>();
            services.AddTransient<IAppLifetime, AppLifetime>();
    
            IServiceProvider aspectCoreServiceProvider = services.BuildAspectCoreServiceProvider();
    
            Console.ReadKey();
        }
    }
    
  3. 参数拦截器定义在AspectCore.Extensions.CrossParameters命名空间下,并已经内置NotNullAttribute进行非空验证,我们来通过继承ParameterInterceptorAttribute来自定义另一个参数拦截器NotNullOrEmptyAttribute:

    public class NotNullOrEmptyAttribute : ParameterInterceptorAttribute
    {
        public override Task Invoke(IParameterDescriptor parameter, ParameterAspectContext context, ParameterAspectDelegate next)
        {
            if (parameter.ParameterType == typeof(string))
            {
                if (string.IsNullOrEmpty(parameter.Value?.ToString()))
                {
                    throw new ArgumentException($"Invalid parameter. {parameter.Name} cannot be null or empty");
                }
            }
            return next(parameter, context);
        }
    }
  4. 定义需要进行参数拦截的方法:

    public interface IAppService
    {
        void Run([NotNull]string[] args);
    
        void Stop([NotNullOrEmpty]string message);
    
        //..
    }
    

    通过AspectCore创建的类型实例便能在运行时对标记了特性的方法参数进行拦截验证。

方法参数注入

在Asp.Net Core MVC中我们通过在Action的参数上标记[FromServices]来进行参数注入。那么在非Controller类和非Action方法中,我们同样可以通过AspectCore完成类似的功能。
定义如下方法:

    public interface IAppService
    {
        Lifetime GetLifetime([Inject]IAppLifetime lifetime = null);
    }

那么我们可以在调用时:

var appService = aspectCoreServiceProvider.GetService<IAppService>();
appService.GetLifetime();

参数IAppLifetime lifetime便会自动在运行时注入到方法中。
本文的示例代码在AspectCore/Sample

AspectCore的后续计划

AspectCore 正式更名为 AspectCore Framework,旨在提供以AOP为核心的跨平台开发框架,正在开发的版本定义为v0.2-preview1,在这个版本中,我们会添加如下基础组件:

  • AspectCore.Extensions.ScopedContext:切面作用域支持
  • AspectCore.Extensions.Reflection : 高性能的反射扩展
  • AspectCore.Extensions.Expression : 表达式树和Emit扩展
  • AspectCore.Extensions.Mapper : 轻量级对象映射库
  • AspectCore.Extensions.DataValidations : 服务层方法的数据验证组件
  • AspectCore.Extensions.CrossProperties : 属性拦截器
©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值