dotnetcore实现aop

   aop大家都不陌生,然而今天给大家不将讲官方的filter,今天给大家分享一个轻量级的aop解决方案(aspectcore)

什么是aspectcore

aspectcore是一个面向切面编程,基于.netcore和.netframwork的扩平台框架,对方法拦截器、依赖项注入集成、web应用程序、数据验证等提供核心支持。

aspectcore基本特性

  • 提供抽象的aop接口,基于该接口可以轻松的使用自己的代理类实现替换默认的实现.

  • 框架不包含ioc,也不依赖具体ioc实现,可以使用asp.net core的内置依赖注入或者任何兼容asp.net core的第三方ioc来继承aspectcore到asp.netcore应用中

  • 高性能的异步拦截系统

  • 灵活的配置系统

  • 基于service的而非基于实现类的切面构造

  • 支持扩平台的asp.net core环境

    使用aspectcore

    从nuget中安装aspectcore

    aspectcore.extensions.dependencyinjection
    

    package

    pm> install-package aspectcore.extensions.dependencyinjection
    

    下面我创建了一个api应用程序.

    nuget安装

    aspectcore.configuration
    

    package

    pm> install-package aspectcore.configuration
    

    下面我新建了一个拦截器 custominterceptorattribute,继承abstractinterceptorattribute(一般情况下继承他即可),他实现iinterceptor接口aspectcore默认实现了基于attribute的拦截器配置。

    /// <summary>
    ///     自定义拦截器
    /// </summary>
    public class custominterceptorattribute : abstractinterceptorattribute
    {
        /// <summary>
        ///     实现抽象方法
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        public override async task invoke(aspectcontext context, aspectdelegate next)
        {
            try
            {
                console.writeline("执行之前");
                await next(context);//执行被拦截的方法
            }
            catch (exception)
            {
                console.writeline("被拦截的方法出现异常");
                throw;
            }
            finally
            {
                console.writeline("执行之后");
            }
        }
    }
    

    定义icustomservice接口和它的实现类customservice:

    public interface icustomservice
    {
        datetime getdatetime();
    }
    public class customservice : icustomservice
    {
        public datetime getdatetime()
        {
            return datetime.now;
    
         }
    }
    

    在valuescontroller注入icustomservice

    [route("api/[controller]")]
    [apicontroller]
    public class valuescontroller : controllerbase
    {
        private readonly icustomservice _icustomserveice;
        public valuescontroller(icustomservice icustomservice) {
            this._icustomserveice = icustomservice;
        }
    
        // get api/values
        [httpget]
        public datetime get()
        {
            return _icustomserveice.getdatetime();
        }
    
    }
    

    注册icustomservice,并创建代理容器

     public iserviceprovider configureservices(iservicecollection services)
            {
                services.addtransient<icustomservice,customservice>();
                services.addmvc();
                //全局拦截器。使用configuredynamicproxy(action<iaspectconfiguration>)的重载方法,其中iaspectconfiguration提供interceptors注册全局拦截器:
                services.configuredynamicproxy(config=> {
                    config.interceptors.addtyped<custominterceptorattribute>();
                });
                services.addmvc().setcompatibilityversion(compatibilityversion.version_2_2);
                return services.buildaspectinjectorprovider();
         }
    

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

    services.addtransient<custominterceptorattribute>(provider => new custominterceptorattribute());
    

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

     services.configuredynamicproxy(config =>
                {
                    config.interceptors.addtyped<custominterceptorattribute>(method => method.declaringtype.name.endswith("service"));
                });
    

    通配符拦截器,匹配后缀为service

     services.configuredynamicproxy(config =>
                {
                    config.interceptors.addtyped<custominterceptorattribute>(predicates.forservice("*service"));
                });
    

    在aspectcore中提供nonaspectattribute来使得servicemethod不被代理:

       [nonaspect]
        datetime getdate();
    

    全局配置忽略条件

      services.configuredynamicproxy(config =>
        {
            //namespace命名空间下的service不会被代理
            config.nonaspectpredicates.addnamespace("namespace");
            //最后一级为namespace的命名空间下的service不会被代理
            config.nonaspectpredicates.addnamespace("*.namespace");
            //icustomservice接口不会被代理
            config.nonaspectpredicates.addservice("icustomservice");
            //后缀为service的接口和类不会被代理
            config.nonaspectpredicates.addservice("*service");
            //命名为method的方法不会被代理
            config.nonaspectpredicates.addmethod("method");
            //后缀为method的方法不会被代理
            config.nonaspectpredicates.addmethod("*method");
        });

aspectcore

https://github.com/dotnetcore/aspectcore-framework

测试项目地址

https://github.com/fhcodegit/dotnetaspectcore/tree/master