网上有不少文章说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);
} }

请忽略其他几个次要的代码,只关注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);
}
}

其他东西先不要看,我们只看一句:

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的形式发布出来。

通俗理解ABP中的模块Module的更多相关文章

  1. ABP中的模块初始化过程(一)

    在总结完整个ABP项目的结构之后,我们就来看一看ABP中这些主要的模块是按照怎样的顺序进行加载的,在加载的过程中我们会一步步分析源代码来进行解释,从而使自己对于整个框架有一个清晰的脉络,在整个Asp. ...

  2. 通俗理解angularjs中的$apply,$digest,$watch

    <!DOCTYPE html> <html lang="zh-CN" ng-app="app"> <head> <me ...

  3. 理解JS中的模块规范(CommonJS,AMD,CMD)

    随着互联网的飞速发展,前端开发越来越复杂.本文将从实际项目中遇到的问题出发,讲述模块化能解决哪些问题,以及如何使用 Sea.js 进行前端的模块化开发. 恼人的命名冲突 我们从一个简单的习惯出发.我做 ...

  4. JQuery选择器大全 前端面试送命题:面试题篇 对IOC和DI的通俗理解 c#中关于协变性和逆变性(又叫抗变)帮助理解

    JQuery选择器大全   jQuery 的选择器可谓之强大无比,这里简单地总结一下常用的元素查找方法 $("#myELement")    选择id值等于myElement的元素 ...

  5. angular6 NgModule中定义模块module

    用这个@NgModule()这个decorator ,放在一个class的上面,这个class一个一个module了 @NgModule() 里面的参数是一个对象,用来配置的,声明这个module里面 ...

  6. ABP中的Filter(上)

    这个部分我打算用上下两个部分来将整个结构来讲完,在我们读ABP中的代码之后我们一直有一个疑问?在ABP中为什么要定义Interceptor和Filter,甚至这两者之间我们都能找到一些对应关系,比如: ...

  7. python 历险记(五)— python 中的模块

    目录 前言 基础 模块化程序设计 模块化有哪些好处? 什么是 python 中的模块? 引入模块有几种方式? 模块的查找顺序 模块中包含执行语句的情况 用 dir() 函数来窥探模块 python 的 ...

  8. ABP中模块初始化过程(二)

    在上一篇介绍在StartUp类中的ConfigureService()中的AddAbp方法后我们再来重点说一说在Configure()方法中的UserAbp()方法,还是和前面的一样我们来通过代码来进 ...

  9. (七)理解angular中的module和injector,即依赖注入

    (七)理解angular中的module和injector,即依赖注入 时间:2014-10-10 01:16:54      阅读:63060      评论:1      收藏:0      [点 ...

随机推荐

  1. jenkins 自动化部署vue前端+java后端项目 进阶一

    今天又不想写了,那么我来将我参考的文章直接分享给大家好了,大家也可以直接进行参考: 这里以centos7为例搭建自动化部署项目: 1.搭建部署前端服务代理nginx: 借鉴于:https://blog ...

  2. pycharm解释器的配置等

    转自:http://www.360doc.com/content/18/0913/14/11881101_786350505.shtml 为什么安装python后,还需要pycharm配置环境 我们实 ...

  3. 不忍了,快速下载Visual Studio Code

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年5月2日. 奇怪的原因 因为一些众所周知的原因,在国内下载Visual Studio Code的速度比较慢,所以我们需要一些方法来加快 ...

  4. 一文带你搞懂 JWT 常见概念 & 优缺点

    在 JWT 基本概念详解这篇文章中,我介绍了: 什么是 JWT? JWT 由哪些部分组成? 如何基于 JWT 进行身份验证? JWT 如何防止 Token 被篡改? 如何加强 JWT 的安全性? 这篇 ...

  5. 七、服务器硬件及RAID配置实战

    一.RAID磁盘阵列介绍 磁盘阵列的全名(Redundant Arrays of Inexpensive Disk,RAID),中文简称是独立冗余磁盘阵列.冗余(如果磁盘出现故障,可以保证数据不丢) ...

  6. Linux安装Anaconda3完整教程

    Linux安装Anaconda3完整教程 欢迎关注H寻梦人公众号 相关链接 官方安装Anaconda3教程 [手把手教你]如何在Linux系统搭建jupyter notebook CentOS8.2安 ...

  7. windows如何结束某个端口的进程

    netstat -ano | findstr 端口号 (查询端口号被哪个进程占用) tasklist | findstr 进程PID (根据PID找到进程名称) taskkill -PID 进程PID ...

  8. 利用MATLAB仿真节点个数和节点通信半径与网络连通率的关系

    一.目的 ①在不同节点个数的情况下,用Matlab拟合出连通率与通信半径的关系曲线. ②在不同节点通信半径的情况下,用Matlab拟合出连通率与节点个数的关系曲线. 二.方法描述 在1x1的单位矩形中 ...

  9. Collection子接口:Set接口

    1.Set 存储的数据特点:无序的.不可重复的元素具体的:以HashSet为例说明: 1. 无序性:不等于随机性.存储的数据在底层数组中并非照数组索引的顺序添加,而是根据数据的哈希值决定的. 2. 不 ...

  10. labview从入门到出家2--将“加法程序”制作成“exe应用程序”

    1.上一章主要讲了如何跑我们的第一个加法程序(这里向第一个程序的鼻祖"hello world"致敬),这一章我们直接进入主题,将我们写的程序生成exe文件放桌面运行. 2.要生成e ...