【ABP框架系列学习】模块系统(4)

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<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);
    }
}

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<MyStartupModule>
    {
    }

    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)

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

模块生命周期(Module Lifetime)

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

原文地址:https://www.cnblogs.com/OlderGiser/p/10014200.html

时间: 2024-11-08 18:55:44

【ABP框架系列学习】模块系统(4)的相关文章

【ABP框架系列学习】N层架构(3)

原文:[ABP框架系列学习]N层架构(3) 目录 0.引言 1.DDD分层 2.ABP应用构架模型 客户端应用程序(Client Applications) 表现层(Presentation Layer) 分布式服务层(Distributed Service Layer) 应用层(Application Layer) 领域层 基础设施层 3.使用ABP项目模版快速生成应用程序 0.引言 应用程序的分层是一种广泛接受的技术, 可以降低复杂度和提高代码的可重用性.为了实现分层架构,ABP遵循领域驱动

【ABP框架系列学习】启动配置(5)

ABP提供了在启动时配置模块的基础设施和模型. 1.配置ABP 配置ABP是在模块的PreInitialize方法中完成的,例如: public class SimpleTaskSystemModule : AbpModule { public override void PreInitialize() { //添加语言 Configuration.Localization.Languages.Add(new LanguageInfo("en", "English"

【ABP框架系列学习】介绍篇(1)

  0.引言 该系列博文主要在[官方文档]及[tkbSimplest]ABP框架理论研究系列博文的基础上进行总结的,或许大家会质问,别人都已经翻译过了,这不是多此一举吗?原因如下: 1.[tkbSimplest]的相关博文由于撰写得比较早的,在参照官方文档学习的过程中,发现部分知识未能及时同步(当前V4.0.2版本),如[EntityHistory].[Multi-Lingual Engities]章节未涉及.[Caching]章节没有Entity Caching等内容. 2.进一步深入学习AB

&lt;&lt;ABP文档 - 框架&gt;&gt; 1.3 模块系统

文档目录 本节内容: 简介 模块定义 生命周期方法 PreInitialize(预初始化) Initialize(初始化) PostInitialize(提交初始化) Shutdown(关闭) 模块依赖 插件模块 Asp.net Core Asp.net Mvc,Web Api 插件中的控制器 附加程序集 自定义模块方法 模块配置 模块生命期 简介 ABP为创建模块及组织它们提供基础框架.一个模块可依赖于另一个模块.通常地,一个程序集做为一个模块.如果你的应用是多个程序集,建议为每个程序集定义一

ABP框架 - 模块系统

模块系统介绍 ABP提供了基础设施功能来构建模块,并通过组合这些模块来创建应用.一个模块可以依赖于另一个模块.一般来讲,一个程序集被认为和定义成一个模块.如果你的应用包含多个程序集,那么你可以为每一个程序集都定义一个模块. 模块定义 ABP中的一个模块是由继承于AbpModule(AbpModule定义在ABP package中)的一个类来定义的.比如我们开发了一个博客模块,可以被不同的应用程序使用,那么一个最简单的博客模块定义如下: public class MyBlogApplication

基于DDD的现代ASP.NET开发框架--ABP系列之4、ABP模块系统

点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之4.ABP模块系统 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ABP的官方网站:http://www.aspnetboilerplate.com ABP在Github上的开源项目:https://github.com/aspnetboilerplate 本文由东莞-天道提供翻译 ABP模块系统简介 ABP框架提供了创建和组装模块的基础,一个模块能够依

ABP模块系统

ABP模块系统 基于DDD的现代ASP.NET开发框架--ABP系列之4.ABP模块系统 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ABP的官方网站:http://www.aspnetboilerplate.com ABP在Github上的开源项目:https://github.com/aspnetboilerplate 本文由东莞-天道提供翻译 ABP模块系统简介 ABP框架提供了创建和组装模块的基础,一个模块能够依赖于另一个模块.

如何用ABP框架快速完成项目(11) - ABP只要加人即可马上加快项目进展- 全栈篇(2) - 不推荐模块组件化, 推荐微服务

一个人写代码不需要担心会和别人的代码冲突, 不需要做代码合并, 不需要担心自己的代码被覆盖. 但是多个人一起写代码就需要担心这些问题. 解决这些问题的方法很多, 比如用AzureDevOps(TFS)来进行代码管理和版本控制等等. 其中有两个办法就是, 业务模块组件化和微服务. 首先ABP是支持业务模块组件化的, 然而我并不推荐在ABP使用业务模块组件化, 因为: ABP更新太快了, 每2周更新一个版本. 除了ABP更新快, 其他技术\框架\工具也更新很快. 正如我在<如何用ABP框架快速完成项

ABP vNext模块系统初试 - 创建留言板模块

上次翻译的ABP vNext介绍发布后,引起了很多ABP好爱者的关注. 那么就趁热打铁,体验一下新ABP. 新的ABP中我最感兴趣的是它的模板系统,所以这次就利用模块系统做了留言板的例子,分享给大家. 留言板模块 我们的留言板模块功能很简单,就是提供用户留言的功能(废话),为了简单起见,功能都非常简陋: 通过菜单进入留言板 显示留言一览,显示的项目有:标题,作者和时间 任意用户可创建留言,修改或删除自己的留言 管理员可修改或删除任何留言 留言只有标题和正文,均为纯文本(不支持富文本). 使用AB