欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ABP之模块系统

程序员文章站 2022-10-06 19:46:56
简介 ASP.NET Boilerplate提供了构建模块的基础结构,并将它们组合在一起以创建应用程序。 模块可以依赖于另一个模块。 通常,一个程序集被视为一个模块。 如果创建具有多个程序集的应用程序,建议您为每个程序集创建一个模块定义。 模块系统目前专注于服务端,而不是客户端。 模块定义 定义一个 ......

简介

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时才可以这样做。

模块配置

虽然可以使用自定义模块方法配置模块,但我们建议您使用启动配置系统来定义和设置模块的配置。

模块声明周期
模块类被自动注册为单例模式。