通俗理解ABP中的模塊Module

  網上有不少文章說ABP的模塊,有的直接翻譯自官網介紹,有的分析Modlue的源代碼,有的寫一通代碼,沒什麼注釋,很少有能通俗說清的。那麼,有兩個問題:1.ABP中的模塊到底是什麼?2.搞這個東西是幹嘛用的?難道是吃撐了沒事做?下面我們來如何通俗回答這兩個問題。

  第一個問題:ABP中的模塊到底是什麼?

  通俗的理解,這個東西就相當於程序集,你開發的項目不是有很多個類庫嗎?或者會有很多個所謂的「項目型」的程序集嗎?如下圖所示:

裏面不是有一堆東西嗎?例如:AbpCompanyName.AbpProjectName.Application,AbpCompanyName.ProjectName.TestModule等等一堆東西,這些東西就是模塊,也就是程序集。這並沒有什麼好稀奇,也沒什麼好神秘的,就是Assembly而已,只不過在ABP中,我們要讓這個程序集成為一個Module模塊,需要在這個程序集里單獨定義一個繼承於AbpModule的類,例如在我的AbpCompanyName.ProjectName.TestModule里,我就定義一個繼承於AbpModule的AbpProjectNameTestModule類,並在它的 Initialize()方法里鼓搗一句註冊的方法: IocManager.RegisterAssemblyByConvention(typeof(AbpProjectNameTestModule).Assembly)即可

如下面代碼所示:

 [DependsOn(typeof(AbpProjectName.AbpProjectNameApplicationModule))]
    public class AbpProjectNameTestModule:AbpModule
    {


        private string _initStr = string.Empty;

        public string InitStr { get { return _initStr; } set { _initStr = value; }}

        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(typeof(AbpProjectNameTestModule).Assembly);
            //base.Initialize();
        }


        public AbpProjectNameTestModule()
        {
            //Init
            _initStr = "AbpProjectNameTestModule() constructor init";
            Console.WriteLine(_initStr);
        }




    }

View Code

請忽略其他幾個次要的代碼,只關注Initialize方法即可。

第二個問題:搞這個東西是幹嘛用的?

  既然這玩意就是程序集,那麼還要費盡心思搞這個模塊幹嘛?豈不多此一舉嗎?難道讓我吃飽了沒事做嗎?當然你可以不用,但用了有什麼好處呢?如果我的項目有多個程序集,其中有一個依賴於其他幾個程序集,如果這個項目一成不變倒沒什麼問題。但是如果有變,要替換其中依賴的一個或者幾個程序集呢?那麼問題就來了,凡是這個項目中有引用到的這些依賴程序集,都要一一替換,所以這個時候,就該使用ABP的模塊了,它用來解決模塊(或者叫程序集)的依賴問題

  ABP中使用模塊依賴來解決這個問題,如果一個模塊需要依賴於其他的模塊,我們只需要在這個模塊的上面寫上屬性DependsOn(XXXX模塊)即可.例如我這裡有一個叫做AbpProjectNameWebModule的模塊,它依賴於AbpProjectNameApplicationModule,AbpProjectNameEntityFrameworkCoreModule,AbpAspNetCoreModule和AbpProjectNameTestModule,我們只需要在AbpProjectNameWebModule的頭部加上這句即可:

[DependsOn(
typeof(AbpProjectNameApplicationModule),
typeof(AbpProjectNameEntityFrameworkCoreModule),
typeof(AbpAspNetCoreModule),
typeof(AbpProjectNameTestModule)
)]

代碼如下所示:

 [DependsOn(
        typeof(AbpProjectNameApplicationModule), 
        typeof(AbpProjectNameEntityFrameworkCoreModule), 
        typeof(AbpAspNetCoreModule),
        typeof(AbpProjectNameTestModule)
        )]
    public class AbpProjectNameWebModule : AbpModule
    {
        private readonly IConfigurationRoot _appConfiguration;

        //構造函數注入 construc inject
        private AbpProjectNameApplicationModule _appModule;

        private AbpProjectNameTestModule _testModule;

        //Property inject
        //public AbpProjectNameApplicationModule _appModule { get; set; }



        public AbpProjectNameWebModule(IWebHostEnvironment env)
        {
            _appConfiguration = AppConfigurations.Get(env.ContentRootPath, env.EnvironmentName);
            //_appModule.A();
        }

        public AbpProjectNameWebModule(AbpProjectNameApplicationModule appModule,AbpProjectNameTestModule testModule)
        {
            //構造函數注入
            _appModule = appModule;

            _testModule = testModule;
        }



        public override void PreInitialize()
        {
            Configuration.DefaultNameOrConnectionString = _appConfiguration.GetConnectionString(AbpProjectNameConsts.ConnectionStringName);

            Configuration.Navigation.Providers.Add<AbpProjectNameNavigationProvider>();

            Configuration.Modules.AbpAspNetCore()
                .CreateControllersForAppServices(
                    typeof(AbpProjectNameApplicationModule).GetAssembly()
                );

            //test1
            _appModule.A();

            //test2
            //string str = _appModule.Bar();

            //test3
            //Baz baz = new Baz();
        }

        public override void Initialize()
        {
            IocManager.RegisterAssemblyByConvention(typeof(AbpProjectNameWebModule).GetAssembly());
        }

        public override void PostInitialize()
        {
            IocManager.Resolve<ApplicationPartManager>()
                .AddApplicationPartsIfNotAddedBefore(typeof(AbpProjectNameWebModule).Assembly);
        }
    }

View Code

其他東西先不要看,我們只看一句:

public AbpProjectNameWebModule(AbpProjectNameApplicationModule appModule,AbpProjectNameTestModule testModule)
{
//構造函數注入
_appModule = appModule;

_testModule = testModule;
}

在AbpProjectNameWebModule構造函數中,我們居然可以不用手動實例化AbpProjectNameApplicationModule和AbpProjectNameTestModule,就可以直接獲取到它們的實例了,是不是很神奇?當然是ABP框架在背後幫我們做了模塊注入的事,具體可以看看AbpBootstrapper,AbpModuleManager,AbpModule等類的代碼,重點關注模塊管理類AbpModuleManager的RegisterModules方法,這個方法就是用來注入所有的模塊,代碼如下所示:

        /// <summary>
        /// 將所有模塊註冊到IOC容器
        /// </summary>
        /// <param name="moduleTypes"></param>
        private void RegisterModules(ICollection<Type> moduleTypes)
        {
            foreach (var moduleType in moduleTypes)
            {
                _iocManager.RegisterIfNot(moduleType);
            }
        }

至於模塊是怎麼加載的,怎樣註冊注入的,又是怎樣初始化和運行的,需要仔細分析上面幾個類的源代碼,下篇再總結,上面涉及的代碼也會以一個demo的形式發佈出來。

Tags: