Asp.Net Core轻量级Aop解决方案:AspectCore
什么是aspectcore project ?
aspectcore project 是适用于asp.net core 平台的轻量级 aop(aspect-oriented programming) 解决方案,它更好的遵循asp.net core的模块化开发理念,使用aspectcore可以更容易构建低耦合、易扩展的web应用程序。aspectcore使用emit实现高效的动态代理从而不依赖任何第三方aop库。
开使使用aspectcore
启动 visual studio。从 file 菜单, 选择 new > project。选择 asp.net core web application 项目模版,创建新的 asp.net core web application 项目。
- 从 nuget 安装 aspectcore.extensions.dependencyinjection package:
- pm> install-package aspectcore.extensions.dependencyinjection
- 在一般情况下可以使用抽象的interceptorattribute自定义特性类,它实现iinterceptor接口。aspectcore默认实现了基于attribute的拦截器配置。我们的自定义拦截器看起来像下面这样:
public class custominterceptorattribute : interceptorattribute { public async override task invoke(iaspectcontext context, aspectdelegate next) { try { console.writeline("before service call"); await next(context); } catch (exception) { console.writeline("service threw an exception!"); throw; } finally { console.writeline("after service call"); } } }
定义icustomservice接口和它的实现类customservice:
public interface icustomservice { [custominterceptor] void call(); } public class customservice : icustomservice { public void call() { console.writeline("service calling..."); } }
在homecontroller中注入icustomservice:
public class homecontroller : controller { private readonly icustomservice _service; public homecontroller(icustomservice service) { _service = service; } public iactionresult index() { _service.call(); return view(); } }
注册icustomservice,接着,在configureservices中配置创建代理类型的容器:
public iserviceprovider configureservices(iservicecollection services) { services.addtransient<icustomservice, customservice>(); services.addmvc(); services.addaspectcore(); return services.buildaspectcoreserviceprovider(); }
拦截器配置。首先安装aspectcore.extensions.configuration package:
pm> install-package aspectcore.extensions.configuration
全局拦截器。使用addaspectcore(action<aspectcoreoptions>)
的重载方法,其中aspectcoreoptions提供interceptorfactories注册全局拦截器:
services.addaspectcore(config => { config.interceptorfactories.addtyped<custominterceptorattribute>(); });
带构造器参数的全局拦截器,在custominterceptorattribute
中添加带参数的构造器:
public class custominterceptorattribute : interceptorattribute { private readonly string _name; public custominterceptorattribute(string name) { _name = name; } public async override task invoke(aspectcontext context, aspectdelegate next) { try { console.writeline("before service call"); await next(context); } catch (exception) { console.writeline("service threw an exception!"); throw; } finally { console.writeline("after service call"); } } }
修改全局拦截器注册:
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(); }
服务定位器模式。拦截器上下文aspectcontext可以获取当前scoped的serviceprovider:
public class custominterceptorattribute : interceptorattribute { public override task invoke(aspectcontext context, aspectdelegate next) { var logger = context.serviceprovider.getservice<ilogger<custominterceptorattribute>>(); logger.loginformation("call interceptor"); return next(context); } }
使用autofac和aspectcore。aspectcore原生支持集成autofac,我们需要安装下面两个nuget packages:
pm> install-package autofac.extensions.dependencyinjection pm> install-package aspectcore.extensions.autofac
aspectcore提供registeraspectcore扩展方法在autofac的container中注册动态代理需要的服务,并提供asinterfacesproxy和asclassproxy扩展方法启用interface和class的代理。修改configureservices方法为:
public iserviceprovider configureservices(iservicecollection services) { services.addmvc(); var container = new containerbuilder(); container.registeraspectcore(); container.populate(services); container.registertype<customservice>().as<icustomservice>().instanceperdependency().asinterfacesproxy(); return new autofacserviceprovider(container.build()); }
有问题反馈
如果您有任何问题,请提交 issue 给我们。
aspectcore project 项目地址:
以上所述是小编给大家介绍的asp.net core轻量级aop解决方案:aspectcore,希望对大家有所帮助
下一篇: Asp.Net Core简介与安装教程
推荐阅读
-
Asp.Net Core轻量级Aop解决方案:AspectCore
-
ASP.NET Core 3.0 使用AspectCore-Framework实现AOP
-
Asp.net Core 3.1基于AspectCore实现AOP实现事务、缓存拦截器功能
-
《ASP.NET Core In Action》读书笔记系列五 ASP.NET Core 解决方案结构解析1
-
ASP.NET Core 2.0 本地文件操作问题及解决方案
-
学习ASP.NET Core Razor 编程系列十八——并发解决方案
-
详解ASP.NET与ASP.NET Core用户验证Cookie并存解决方案
-
asp.net core 2.0发布到IIS报错解决方案
-
asp.net core3.1 引用的元包dll版本兼容性问题解决方案
-
ASP.NET Core 2.0 本地文件操作问题及解决方案