天天看點

【ABP架構系列學習】子產品系統(4)0.引言1.子產品定義2.生命周期方法3.子產品依賴(Module Dependencies)4.插件子產品ASP.NET MVC,Web API附加程式集(Additional Assemblies)自定義子產品方法(Custom Module Methods)子產品配置(Module Configuration)子產品生命周期(Module Lifetime)

原文: 【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)。

繼續閱讀