ABP提供了基础设施功能来构建模块,并经过组合这些模块来建立应用。一个模块能够依赖于另外一个模块。通常来说,一个程序集被认为和定义成一个模块。若是你的应用包含多个程序集,那么你能够为每个程序集都定义一个模块。web
ABP中的一个模块是由继承于AbpModule(AbpModule定义在ABP package中)的一个类来定义的。好比咱们开发了一个博客模块,能够被不一样的应用程序使用,那么一个最简单的博客模块定义以下:c#
public class MyBlogApplicationModule : AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } }
定义模块的类有一个职责就是经过依赖注入来注册模块中的类型,如上代码所示:api
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
固然,除此以外,它还能够配置应用程序,实现新的功能等等安全
当应用程序启动和关闭时,ABP会调用模块中的一组特定方法PreInitialize、Initialize、PostInitialize、Shutdown。你能够重写这些方法来执行特定任务。mvc
ABP是根据模块之间的依赖顺序来执行模块的这些方法的。例如模块A依赖于模块B,那么模块B就会在模块A以前作初始化。当应用程序启动时,模块A和模块B中这些方法的执行顺序以下:PreInitialize-B-->PreInitialize-A-->Initialize-B-->Initialize-A-->PostInitialize-B-->PostInitialize-Aapp
当应用程序关闭时,过程与启动相似,只是执行顺序与启动时是相反的。框架
当启动时,会首先调用PreInitialize方法,它在模块初始化以前执行,因此一般会将框架和模块的配置定义在这里。同时,一些在依赖注入以前执行的代码也会写在这里。例如你定义一个传统的类,那么你须要在这里调用 IocManager.AddConventionalRegisterer 方法来注册它。asp.net
在Initialize方法中,会经过依赖注入注册模块中定义的类型,通常使用IocManager.RegisterAssemblyByConvention 方法来来注册,固然也可自定义类型注册。ide
在启动过程当中,这是最后一个被调用的方法。在这里能够安全的解析一个依赖。函数
在应用关闭时,会调用此方法。
一个模块能够依赖于另外一个模块,你须要使用DependsOn特性来显示的定义模块间的依赖关系,以下所示:
[DependsOn(typeof(MyBlogCoreModule))] public class MyBlogApplicationModule : AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } }
在这里,咱们定义MyBlogApplicationModule模块依赖于MyBlogCoreModule模块,而且MyBlogCoreModule模块要在MyBlogApplicationModule模块以前进行初始化。
ABP在启动模块中,自动的解析模块之间的依赖关系并初始化模块。启动模块是最后一个被初始化的模块。
ABP能够在启动模块中检测、加载模块集,也能够动态的加载模块,这些动态加载的模块就称之为插件模块。
在动态加载模块时,要指定插件模块的源,在AbpBootstrapper类中定义了一个属性PlugInSources, 就是用来指定插件模块的源。任何一个实现了IPlugInSource接口的类均可以用来定义插件模块的源。
在ABP中提供了一个默认实现PlugInFolderSource, 用于从指定的文件夹中获取插件模块。
在ABP ASP.NET Core模块的Startup类中,ABP为AddAbp扩展方法定义了添加插件模块源的选项:
services.AddAbp<MyStartupModule>(options => { options.PlugInSources.Add(new FolderPlugInSource(@"C:\MyPlugIns")); });
也可使用AddFolder扩展方法
services.AddAbp<MyStartupModule>(options => { options.PlugInSources.AddFolder(@"C:\MyPlugIns"); });
若是是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); } }
若是你在插件模块中定义了MVC / Web API Controllers, ASP.NET将不能检测到这些Controllers, 要解决这个问题,你须要修改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(); } } }
在ABP中定义了两个接口IAssemblyFinder和ITypeFinder,这两个接口是ABP用来检测应用中的程序中的程序集和类型的。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的方法了,可是前提条件是MyModule2模块依赖MyModule1模块。
ABP中建议使用启动配置(startup configuration)来配置模块
定义模块的类会被自动注册为单例