企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## 1.3 ABP总体介绍 - 模块系统 ### 1.3.1 ABP模块系统简介 ABP框架提供了创建和组装模块的基础,一个模块能够依赖于另一个模块。在通常情况下,一个程序集就可以看成是一个模块。在ABP框架中,一个模块通过一个类来定义,而这个类要继承自AbpModule。 >译者注: 如果学习过Orchard的朋友,应该知道module模块的强大了。模块的本质就是可重用性,你可以在任意的地方去调用,而且通过实现模块,你写的模块也可以给别人用。.net可以通过反射获取一个程序集中的类以及方法。 Assembly程序集:Assembly是一个用来包含程序的名称,版本号,自我描述,文件关联关系和文件位置等信息的一个集合。最简单的理解就是:一个你自己写的类库生成的dll就可以看做是一个程序集,这个程序集可以包括很多类,类又包括很多方法等。 下面的例子,我们开发一个可以在多个不同应用中被调用MybolgApplication模块,代码如下: ```csharp public class MyBlogApplicationModule : AbpModule //定义 { public override void Initialize() //初始化 { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); //这行代码的写法基本上是不变的。它的作用是把当前程序集的特定类或接口注册到依赖注入容器中。 } } ``` ABP框架会扫描所有的程序集,并且发现AbpModule类中所有已经导入的类,如果你已经创建了包含多个程序集的应用,对于ABP,我们的建议是为每一个程序集创建一个Module(模块)。 ### 1.3.2 生命期事件 在一个应用中,ABP框架调用了Module模块的一些指定的方法来进行启动和关闭模块的操作。我们可以重载这些方法来完成我们自己的任务。 ABP框架通过依赖关系的顺序来调用这些方法,假如:模块A依赖于模块B,那么模块B要在模块A之前初始化,模块启动的方法顺序如下: 1. PreInitialize-B * PreInitialize-A * Initialize-B * Initialize-A * PostInitialize-B * PostInitialize-A 下面是具体方法的说明: **PreInitialize** 预初始化:当应用启动后,第一次运行会先调用这个方法。在依赖注入注册之前,你可以在这个方法中指定你需要注入的自定义启动类。举个例子吧:假如你创建了一个自定义的TestAbpSession : IAbpSession,那么请在这个方法中对TestAbpSession进行注册。 **Initialize** 初始化:在这个方法中一般是来进行依赖注入的注册,一般我们通过IocManager.RegisterAssemblyByConvention这个方法来实现。如果你想实现自定义的依赖注入,那么请参考依赖注入的相关文档。 **PostInitialize** 提交初始化:最后一个方法,这个方法用来解析依赖关系。 **Shutdown** 关闭:当应用关闭以后,这个方法被调用。 ### 1.3.3 模块依赖 Abp框架会自动解析模块之间的依赖关系,但是我们还是建议你通过重载GetDependencies方法来明确的声明依赖关系。 ```csharp [DependsOn(typeof(MyBlogCoreModule))]//通过注解来定义依赖关系 public class MyBlogApplicationModule : AbpModule { public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } } ``` 例如上面的代码,我们就声明了MyBlogApplicationModule和MyBlogCoreModule的依赖关系(通过属性attribute),MyBlogApplicationModule这个应用模块依赖于MyBlogCoreModule核心模块,并且,MyBlogCoreModule核心模块会在MyBlogApplicationModule模块之前进行初始化。 ### 1.3.4 插件模块 当模块从启动模块以及其依赖关系进行调查发现的时候,ABP也能够动态的加载其它指定模块。**AbpBootstrapper** 类定义了 **PlugInSources** 属性,我们能够是用该属性添加需要动态加载的模块。插件源可以是任何实现了 **IPlugInSource** 接口的类。**PlugInFolderSource** 类实现了该接口,它可以被用来加载指定文件夹下的程序集。 #### ASP.NET Core ABP的ASP.NET Core模块也可以动态加载模块,你只需要在 **Startup** 类中使用已定义的扩展方法 **AddAbp**,如下所示: ```csharp services.AddAbp<MyStartupModule>(options => { options.PlugInSources.Add(new FolderPlugInSource(@"C:\MyPlugIns")); }); ``` 我们可以使用扩展方法 **AddFolder** 更方便的实现上述功能: ```csharp services.AddAbp<MyStartupModule>(options => { options.PlugInSources.AddFolder(@"C:\MyPlugIns"); }); ``` 了解更多关于Startup类的信息,请查看 [ASP.NET 文档](225864) #### ASP.NET MVC,Web API 对于经典的ASP.NET MVC应用,我们可以在 **global.asax** 重写 **Application_Start** 方法来添加插件文件夹,如下所示: ```csharp public class MvcApplication : AbpWebApplication<MyStartupModule> { protected override void Application_Start(object sender, EventArgs e) { AbpBootstrapper.PlugInSources.AddFolder(@"C:\MyPlugIns"); //... base.Application_Start(sender, e); } } ``` #### Additional Assemblies 对于IAssemblyFinder和ITypeFinder的默认实现(这两个接口的实现被ABP用来在应用程序中发现指定的类)仅仅只用来查找模块程序集以及在这些程序集中所使用的类型。我们可以在我们的模块中重写 **GetAdditionalAssemblies** 方法来包含附加程序集。 ### 1.3.5 自定义的模块方法 我们自己定义的模块中可能有方法被其他依赖于当前模块的模块调用,下面的例子,假设模块2依赖于模块1,并且想在预初始化的时候调用模块1的方法。这样,就把模块1注入到了模块2,因此,模块2就能调用模块1的方法了。 >译者注: ABP的模块系统与Orchard的模块有类似之处,但还是有比较大的差别。Orchard的框架修改了ASP.NET程序集的默认加载方式(模块的DLL没有放在Bin文件夹下,是放在WEB项目根文件夹下面的Modules文件夹下),实现了功能模块的热插拔,而ABP的模块程序集还是放在Bin文件夹下的,没有实现热插拔。 ```csharp public class MyModule1 : AbpModule { public override void Initialize() //初始化模块 { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());//这里,进行依赖注入的注册。 } public void MyModuleMethod1() { //这里写自定义的方法。 } } [DependsOn(typeof(MyModule1))] public class MyModule2 : AbpModule { private readonly MyModule1 _myModule1; public MyModule2(MyModule1 myModule1) { _myModule1 = myModule1; } public override void PreInitialize() { _myModule1.MyModuleMethod1(); //调用MyModuleMethod1的方法。 } public override void Initialize() { IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly()); } } ```