博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【ABP框架系列学习】模块系统(4)
阅读量:7236 次
发布时间:2019-06-29

本文共 4928 字,大约阅读时间需要 16 分钟。

原文:

0.引言

ABP提供了构建模块和通过组合模块以创建应用程序的基础设施。一个模块可以依赖于另外一个模块。通常,程序集可以认为是模块。如果创建多个程序集的应用程序,建议为每个程序集创建模块定义。

当前,模块系统主要集中在服务器,而不是客户端。

1.模块定义

模块是从ABP包中的AbpModule派生的类定义的。比如说开发一个可以用于不同应用程序的博客模块(Blog Module)。最简单的模块定义如下 :

public class MyBlogApplicationModule : AbpModule{    public override void Initialize()    {        IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());    }}

模块定义类负责通过依赖注入注册类,如有必要(可以像上述事例按惯例完成)。它还可以配置应用程序和其它模块,给应用程序增加新的功能等等。

2.生命周期方法

ABP在程序启动和关闭时调用模块一些特定的方法。你可以重写这些方法以执行某些特定的任务。

ABP按照依赖顺序调用这些方法。如果模块A依赖模块B,那么模块B在模块A之前初始化。

启动方法执行准确的顺序:PreInitialize-B, PreInitialize-A, Initialize-B, Initialize-A, PostInitialize-B, PostInitialize-A。对于所有依赖关系图都是如此。关闭方法也是类似的,但顺序相反。

相关源码:模块启动时依次执行PreInitialize()、Initialize()、PostInitialize(),模块关闭时首先Reverse()、然后在逐个模块Shutdown()。

public virtual void StartModules()        {            var sortedModules = _modules.GetSortedModuleListByDependency();            sortedModules.ForEach(module => module.Instance.PreInitialize());            sortedModules.ForEach(module => module.Instance.Initialize());            sortedModules.ForEach(module => module.Instance.PostInitialize());        }        public virtual void ShutdownModules()        {            Logger.Debug("Shutting down has been started");            var sortedModules = _modules.GetSortedModuleListByDependency();            sortedModules.Reverse();            sortedModules.ForEach(sm => sm.Instance.Shutdown());            Logger.Debug("Shutting down completed.");        }

PreInitialize

当应用程序启动时,首先调用该方法。它是框架和其它模块初始化之前配置它们的首选方法。

你还可以在该方法中编写特定的代码,以便在依赖注入注册之前运行。例如,如果你创建一个传统的注册类,那么你应在该方法中使用IOCManager.AddConventionalRegisterer方法注册它们。

Initialize

该方法是依赖注入注册的地方,通过使用IocManager.RegisterAssemblyByConvention方法完成注册。如果想定义自定义的依赖注册,请见后续依赖注入章节。

PostInitialize

该方法在程序启动的最后调用。在这里解析依赖是安全的。

Shutdown

该方法在程序关闭时调用。

3.模块依赖(Module Dependencies)

一个模块可以依赖于另外的模块。你可以通过DependsOn特性显示声明依赖项,如下代码:

[DependsOn(typeof(MyBlogCoreModule))]public class MyBlogApplicationModule : AbpModule{    public override void Initialize()    {        IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());    }}

上述事例代码中,声明了MyBlogApplicationModule模块依赖于MyBlogCoreModule模块,那么MyBlogCoreModule模块应该在MyBlogApplicationModule模块之前完成初始化。

ABP可以从启动模块(start module)开始就递归的解析依赖关系,并相应地初始化它们。启动模块(start module)是最后进行初始化的模块。

4.插件模块

虽然模块从启动模块开始查找并遍历依赖关系,ABP还可以动态加载模块。AbpBootstrapper类中定义了PlugInSources属性,该属性可用于向动态加载的插件模块添加源。插件源可以是实现IPlugInSource接口的任何类。通过实现FolderPlugInSource类以从指定文件夹中的程序集获取插件模块。

ASP.NET CORE

ABP中ASP.NET CORE模块在AddAbp扩展方法中定义选项,用于在启动类中添加插件源:

services.AddAbp
(options =>{ options.PlugInSources.Add(new FolderPlugInSource(@"C:\MyPlugIns"));});

也可以使用更简单的语法AddFolder扩展方法:

services.AddAbp
(options =>{ options.PlugInSources.AddFolder(@"C:\MyPlugIns");});

ASP.NET MVC,Web API

对于传统的ASP.NET MVC应用程序,可以通过重写global.asax文件中Application_Start方法添加插件文件夹,如下代码:

public class MvcApplication : AbpWebApplication
{ protected override void Application_Start(object sender, EventArgs e) { AbpBootstrapper.PlugInSources.AddFolder(@"C:\MyPlugIns"); //... base.Application_Start(sender, e); }}

Controllers in PlugIns

如果你的模块包括MVC或Web API Controolers,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
{ } public static class PreStarter { public static void Start() { //... MvcApplication.AbpBootstrapper.PlugInSources.AddFolder(@"C:\MyPlugIns\"); MvcApplication.AbpBootstrapper.PlugInSources.AddToBuildManager(); } }}

附加程序集(Additional Assemblies)

默认实现IAssemblyFinder和ITypeFinder接口只能在这些程序集中查找模块程序集和类型。也可以在模块中重写GetAdditionalAssembliesy方法来包括其它程序集。

自定义模块方法(Custom Module Methods)

你的模块还可以拥有自定义的方法,并能在依赖于这个模块的其它模块中调用这个方法。假设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。

模块配置(Module Configuration)

然而自定义方法可以用来配置模块,建议使用启动配置()系统来定义和设置模块的配置。

模块生命周期(Module Lifetime)

模块类自动注册为单实例对象(singleton)。

转载地址:http://xqgfm.baihongyu.com/

你可能感兴趣的文章
《Adobe Illustrator CS5中文版经典教程》—第0课0.17节使用透视
查看>>
Linux 爆新漏洞,长按回车 70 秒可获得 root 权限
查看>>
《用友ERP-U8完全使用详解》——第2章 安装用友ERP-U8(V8.72) 2.1 安装用友ERP-U8(V8.72)软件...
查看>>
海底机器人 OpenROV : 可以让普通人探索深海
查看>>
《Storm企业级应用:实战、运维和调优》——1.2 Storm是什么
查看>>
《Photoshop Lightroom5经典教程》目录—导读
查看>>
《LDA漫游指南》——2.7 总结
查看>>
《深入实践Spring Boot》一1.2 创建项目工程
查看>>
《流量的秘密 Google Analytics网站分析与商业实战》一导读
查看>>
《HTML5和CSS3快速参考》——导读
查看>>
科学家画出了完整的生命树
查看>>
《JavaScript设计模式》——1.5 真假对象
查看>>
Mining the Social Web
查看>>
《JavaScript入门经典(第6版)》——2.3 变量
查看>>
《Java遗传算法编程》—— 1.3 进化计算的历史
查看>>
2014年5个最流行前端框架对比
查看>>
使用Ruby amb解决说谎者谜题
查看>>
弗拉特利定律:Illumina如何缔造基因革命
查看>>
世界六大银行巨头重金押注哪些金融科技初创公司?
查看>>
还有两场,阿里聚安全在广州和上海等你
查看>>