ABP之模块系统
简介
asp.net boilerplate提供了构建模块的基础结构,并将它们组合在一起以创建应用程序。 模块可以依赖于另一个模块。 通常,一个程序集被视为一个模块。 如果创建具有多个程序集的应用程序,建议您为每个程序集创建一个模块定义。
模块系统目前专注于服务端,而不是客户端。
模块定义
定义一个派生自abp包中的abpmodule的类作为一个模块。假设我们现在正在开发一个可以在不同应用程序中使用的blog模块。最简单的模块定义如下:
public class myblogapplicationmodule : abpmodule { public override void initialize() { iocmanager.registerassemblybyconvention(assembly.getexecutingassembly()); } }
如果需要,模块定义类负责通过依赖注入(di)来注册它的类(它可以按常规方式完成,如上所示)。 它还可以配置应用程序和其他模块,为应用程序添加新功能等等......
生命周期方法
abp在应用程序启动和关闭时调用某些特定的模块方法。我们可以覆盖这些方法去执行特定的任务。abp按照依赖顺序来调用这些方法。如果模块a依赖于模块b,模块b就在模块a之前初始化。
启动方法的正确顺序:preinitialize-b,preinitialize-a,initialize-b,initialize-a,postinitialize-b和postinitialize-a。 所有依赖图都是如此。 关闭方法也类似,但顺序相反。
预初始化(preinitialize)
当应用程序启动时,首先调用此方法。它是在初始化之前配置框架和其他模块要执行的方法。
我们也可以在这里编写一些特定的代码,然后在依赖注入注册之前执行。例如,如果是创建传统的注册类,则应使用iocmanager.addconventionalregisterer方法在此处注册。
初始化(initialize)
这是应该完成依赖注入注册的地方,它通常使用iocmanager.registerassemblybyconvention方法完成。也可以自定义依赖注入注册,到时请参阅依赖注入文档(后续写了会加链接)。
初始化后(postinitialize)
此方法在启动过程中最后调用。 在这里解决依赖是安全的。
关闭(shutdown)
应用程序关闭时调用此方法。
模块依赖
模块可以依赖于另一个模块。 我们需要使用dependson属性显式声明依赖项,如下所示:
[dependson(typeof(myblogcoremodule))] public class myblogapplicationmodule : abpmodule { public override void initialize() { iocmanager.registerassemblybyconvention(assembly.getexecutingassembly()); } }
在这里,我们声明myblogapplicationmodule依赖于myblogcoremodule,并且myblogcoremodule应在myblogapplicationmodule之前初始化。
abp可以从启动模块开始递归地解析依赖关系并相应地初始化它们,启动模块初始化为最后一个模块。
插件模块(plugin modules)
虽然从启动模块开始通过依赖项调查模块,但anp也可以动态加载模块,abpbootstrapper类定义了pluginsources属性,该属性可用于添加资源以动态加载插件模块。插件源可以是实现ipluginsource接口的任何类, pluginfoldersource类实现从文件夹中的程序集获取插件模块。
asp.net core
abp asp.net core在addabp扩展方法中定义选项,就是为了实现在startup类中添加插件源。
services.addabp<mystartupmodule>(options => { options.pluginsources.add(new folderpluginsource(@"c:\myplugins")); });
我们也可以调用addfolder来实现最简单的语法。
services.addabp<mystartupmodule>(options => { options.pluginsources.addfolder(@"c:\myplugins"); });
asp.net mvc, web api
对于传统的asp.net mvc应用程序,我们可以通过覆盖global.asax中的application_start来添加插件文件夹,如下所示:
public class mvcapplication : abpwebapplication<mystartupmodule> { protected override void application_start(object sender, eventargs e) { abpbootstrapper.pluginsources.addfolder(@"c:\myplugins"); //... base.application_start(sender, e); } }
plugins中的控制器
如果你的模块包含mvc或web api控制器,则asp.net无法识别你的控制器。 要解决此问题,可以更改global.asax文件,如下所示:
using system.web; using abp.plugins; using abp.web; using mydemoapp.web; [assembly: preapplicationstartmethod(typeof(prestarter), "start")] namespace mydemoapp.web { public class mvcapplication : abpwebapplication<mystartupmodule> { } public static class prestarter { public static void start() { //... mvcapplication.abpbootstrapper.pluginsources.addfolder(@"c:\myplugins\"); mvcapplication.abpbootstrapper.pluginsources.addtobuildmanager(); } } }
附加组件
iassemblyfinder和itypefinder的默认实现(用于abp识别应用程序中的特定类)仅时在这些程序集中查找模块程序集和类型。 我们可以覆盖模块中的getadditionalassemblies方法来包含其他程序集。
自定义模块
模块中也可以有一些被其他依赖模块所使用的自定义方法。 假设mymodule2依赖于mymodule1并想要在preinitialize方法中调用mymodule1的方法:
public class mymodule1 : abpmodule { public override void initialize() { iocmanager.registerassemblybyconvention(assembly.getexecutingassembly()); } public void mymodulemethod1() { //this is a custom method of this module } } [dependson(typeof(mymodule1))] public class mymodule2 : abpmodule { private readonly mymodule1 _mymodule1; public mymodule2(mymodule1 mymodule1) { _mymodule1 = mymodule1; } public override void preinitialize() { _mymodule1.mymodulemethod1(); //call mymodule1's method } public override void initialize() { iocmanager.registerassemblybyconvention(assembly.getexecutingassembly()); } }
这里我们将构造函数注入mymodule1到mymodule2,因此mymodule2可以调用mymodule1的自定义方法。 仅当module2依赖于module1时才可以这样做。
模块配置
虽然可以使用自定义模块方法配置模块,但我们建议您使用启动配置系统来定义和设置模块的配置。
模块声明周期
模块类被自动注册为单例模式。