介绍

我们知道ABP中模块的配置都是通过模块的Configuration属性来设置的。例如在模块的生命周期方法中可以进行一系列的配置 审计 MQ Redis....也可以替换一些ABP默认配置

通常我们的用户模块(自定义模块)都会继承自AbpModule,它是ABP所有模块的基类.也是个抽象类.

  1. public abstract class AbpModule
  2. {
  3. protected internal IIocManager IocManager { get; internal set; }
  4. protected internal IAbpStartupConfiguration Configuration { get; internal set; }
  5. // 其他代码
  6. }

这里的两个属性分别是IIocManager和IAbpStartupConfiguration,所以我们的用户模块可以使用.

IocManager已经研究过了,现在来看看IAbpStartupConfiguration,先看看类关系图



可以看到ABP一系列的基础设施都在里面,授权 事件总线 等等.

启动流程

IAbpStartupConfiguration注册,初始化其实都是在ABPBootStrap的初始化方法中执行的.

  1. public virtual void Initialize()
  2. {
  3. // 其他代码
  4. try
  5. {
  6. // 注册了相关基础设施的配置
  7. IocManager.IocContainer.Install(new AbpCoreInstaller());
  8. IocManager.Resolve<AbpStartupConfiguration>().Initialize();
  9. // 相关模块方法
  10. }
  11. }

可以看到首先已单例的形式注册了一些基础设施.然后从容器中取出AbpStartupConfiguration执行Initialize方法

  1. public void Initialize()
  2. {
  3. Localization = IocManager.Resolve<ILocalizationConfiguration>();
  4. Modules = IocManager.Resolve<IModuleConfigurations>();
  5. Features = IocManager.Resolve<IFeatureConfiguration>();
  6. Navigation = IocManager.Resolve<INavigationConfiguration>();
  7. Authorization = IocManager.Resolve<IAuthorizationConfiguration>();
  8. Validation = IocManager.Resolve<IValidationConfiguration>();
  9. Settings = IocManager.Resolve<ISettingsConfiguration>();
  10. UnitOfWork = IocManager.Resolve<IUnitOfWorkDefaultOptions>();
  11. EventBus = IocManager.Resolve<IEventBusConfiguration>();
  12. MultiTenancy = IocManager.Resolve<IMultiTenancyConfig>();
  13. Auditing = IocManager.Resolve<IAuditingConfiguration>();
  14. Caching = IocManager.Resolve<ICachingConfiguration>();
  15. BackgroundJobs = IocManager.Resolve<IBackgroundJobConfiguration>();
  16. Notifications = IocManager.Resolve<INotificationConfiguration>();
  17. EmbeddedResources = IocManager.Resolve<IEmbeddedResourcesConfiguration>();
  18. EntityHistory = IocManager.Resolve<IEntityHistoryConfiguration>();
  19. CustomConfigProviders = new List<ICustomConfigProvider>();
  20. ServiceReplaceActions = new Dictionary<Type, Action>();
  21. }

主要是从容器中取出Configuration,为AbpStartupConfiguration对应的属性赋值.以及初始化工作.

ServiceReplaceActions是一个键值对的集合,这是我们以后替换默认基础配置需要用到的.

Ps:IAbpStartupConfiguration是ABPModule的一个属性,已依赖注入的方式早已经注入进容器,所以我们的自定义模块可以很方便的对一些基础设施做出配置.

例如Configuration.Caching..... | Configuration.Auditing..... 等等

自定义模块设置

  1. internal class AbpStartupConfiguration : DictionaryBasedConfig, IAbpStartupConfiguration

可以看到我们的AbpStartupConfiguration还继承自DictionaryBasedConfig,这个类定义如下:

  1. namespace Abp.Configuration
  2. {
  3. /// <summary>
  4. /// Used to set/get custom configuration.
  5. /// </summary>
  6. public class DictionaryBasedConfig : IDictionaryBasedConfig
  7. {
  8. /// <summary>
  9. /// Dictionary of custom configuration.
  10. /// </summary>
  11. protected Dictionary<string, object> CustomSettings { get; private set; }
  12. /// <summary>
  13. /// Gets/sets a config value.
  14. /// Returns null if no config with given name.
  15. /// </summary>
  16. /// <param name="name">Name of the config</param>
  17. /// <returns>Value of the config</returns>
  18. public object this[string name]
  19. {
  20. get { return CustomSettings.GetOrDefault(name); }
  21. set { CustomSettings[name] = value; }
  22. }
  23. /// <summary>
  24. /// Constructor.
  25. /// </summary>
  26. protected DictionaryBasedConfig()
  27. {
  28. CustomSettings = new Dictionary<string, object>();
  29. }
  30. /// <summary>
  31. /// Gets a configuration value as a specific type.
  32. /// </summary>
  33. /// <param name="name">Name of the config</param>
  34. /// <typeparam name="T">Type of the config</typeparam>
  35. /// <returns>Value of the configuration or null if not found</returns>
  36. public T Get<T>(string name)
  37. {
  38. var value = this[name];
  39. return value == null
  40. ? default(T)
  41. : (T) Convert.ChangeType(value, typeof (T));
  42. }
  43. /// <summary>
  44. /// Used to set a string named configuration.
  45. /// If there is already a configuration with same <paramref name="name"/>, it's overwritten.
  46. /// </summary>
  47. /// <param name="name">Unique name of the configuration</param>
  48. /// <param name="value">Value of the configuration</param>
  49. public void Set<T>(string name, T value)
  50. {
  51. this[name] = value;
  52. }
  53. /// <summary>
  54. /// Gets a configuration object with given name.
  55. /// </summary>
  56. /// <param name="name">Unique name of the configuration</param>
  57. /// <returns>Value of the configuration or null if not found</returns>
  58. public object Get(string name)
  59. {
  60. return Get(name, null);
  61. }
  62. /// <summary>
  63. /// Gets a configuration object with given name.
  64. /// </summary>
  65. /// <param name="name">Unique name of the configuration</param>
  66. /// <param name="defaultValue">Default value of the object if can not found given configuration</param>
  67. /// <returns>Value of the configuration or null if not found</returns>
  68. public object Get(string name, object defaultValue)
  69. {
  70. var value = this[name];
  71. if (value == null)
  72. {
  73. return defaultValue;
  74. }
  75. return this[name];
  76. }
  77. /// <summary>
  78. /// Gets a configuration object with given name.
  79. /// </summary>
  80. /// <typeparam name="T">Type of the object</typeparam>
  81. /// <param name="name">Unique name of the configuration</param>
  82. /// <param name="defaultValue">Default value of the object if can not found given configuration</param>
  83. /// <returns>Value of the configuration or null if not found</returns>
  84. public T Get<T>(string name, T defaultValue)
  85. {
  86. return (T)Get(name, (object)defaultValue);
  87. }
  88. /// <summary>
  89. /// Gets a configuration object with given name.
  90. /// </summary>
  91. /// <typeparam name="T">Type of the object</typeparam>
  92. /// <param name="name">Unique name of the configuration</param>
  93. /// <param name="creator">The function that will be called to create if given configuration is not found</param>
  94. /// <returns>Value of the configuration or null if not found</returns>
  95. public T GetOrCreate<T>(string name, Func<T> creator)
  96. {
  97. var value = Get(name);
  98. if (value == null)
  99. {
  100. value = creator();
  101. Set(name, value);
  102. }
  103. return (T) value;
  104. }
  105. }
  106. }

这里维护了一个protected Dictionary<string, object> CustomSettings { get; private set; }字典,key是字符串类型,value是一个object. 用来存放配置类的,看上述代码可知,还有一些get方法。用来获取配置

用的话也比较简单,只需要在模块的预初始化方法中向DI容器注册配置类即可.

  1. public override void PreInitialize()
  2. {
  3. // BlogWebCoreConfigration 里可以设置具体的配置,这里简略了.
  4. IocManager.Register(typeof(IBlogWebCoreConfigration), typeof(BlogWebCoreConfigration));
  5. }

AbpStartupConfiguration有个public IModuleConfigurations Modules { get; private set; },这个接口主要是让我们加入自定义的配置

  1. public interface IModuleConfigurations
  2. {
  3. /// <summary>
  4. /// Gets the ABP configuration object.
  5. /// </summary>
  6. IAbpStartupConfiguration AbpConfiguration { get; }
  7. }

所以我们只需要写个静态类用扩展方法即可

  1. public static class BlogWebCoreConfigrationExt
  2. {
  3. public static IBlogWebCoreConfigration BlogWebCoreModule(this IModuleConfigurations configuration)
  4. {
  5. return configuration.AbpConfiguration.Get<IBlogWebCoreConfigration>();
  6. }
  7. }

随后我们即可在预初始化方法中 进行配置了

例如;

  1. Configuration.Modules.BlogWebCoreModule().xxxx= true;

自定义配置总流程就是

1.创建一个模块配置类,写上你需要配置的东西

2.创建一个IModuleConfigurations的扩展方法,用AbpConfiguration属性从容器中获取配置类

3.在预初始化方法中调用静态方法即可

替换ABP默认服务

IAbpStartupConfiguration中提供了一个ReplaceService方法

  1. public void ReplaceService(Type type, Action replaceAction)
  2. {
  3. ServiceReplaceActions[type] = replaceAction;
  4. }

作用就是像键值对集合中添加个Key和value,replaceAction是具体要怎么做.

这个方法和我们平时看到的替换服务的方法不一样,我们猜测肯定有扩展方法,根据具体引用查看,

  1. public static void ReplaceService<TType, TImpl>(this IAbpStartupConfiguration configuration, DependencyLifeStyle lifeStyle = DependencyLifeStyle.Singleton)
  2. where TType : class
  3. where TImpl : class, TType
  4. {
  5. configuration.ReplaceService(typeof(TType), () =>
  6. {
  7. configuration.IocManager.Register<TType, TImpl>(lifeStyle);
  8. });
  9. }

果然没错,跟着引用找到了这个方法,这里就是调用了 上述方法,向容器中注册了服务。

那么是什么时候执行注册的呢?

既然它是个集合,还储存了注册的方法.那么我们直接跟着这个集合的引用找一下就可以了.

最终找到是在AbpKernelModule的初始化方法中的执行的.

  1. public override void Initialize()
  2. {
  3. foreach (var replaceAction in ((AbpStartupConfiguration)Configuration).ServiceReplaceActions.Values)
  4. {
  5. replaceAction();
  6. }
  7. // 其他代码 略.
  8. }

这里从AbpMoudel获取AbpStartupConfiguration并遍历它的value(向容器中注册组件action),并调用.

也就是在这里完成了注册.之前也探索过Abp核心模块永远是一个执行初始化方法的,也就确保了我们自己的组件顺利替换

那么问题来了,我们在哪里可以替换配置?

先理一下,首先,执行替换配置服务的核心方法是在abp核心模块的Initialize方法(第一行)中执行的.

执行完成,容器中就已经有了,那肯定是在abp核心模块执行Initialize方法前,我们调用Configuration.ReplaceService方法,将类型和action委托存入字典对象中

之前也说过模块的生命周期执行方法顺序,先是执行所有模块的PreInitialize,然后执行所有模块的Initialize,最后执行PostInitialize

所以很明显,我们需要在自定义模块中的PreInitialize中执行替换方法.

  1. public override void PreInitialize()
  2. {
  3. Configuration.ReplaceService<Ixxxxx, xxxx>(DependencyLifeStyle.Transient);
  4. }

ABP模块配置的更多相关文章

  1. [Abp 源码分析]四、模块配置

    0.简要介绍 在 Abp 框架当中通过各种 Configuration 来实现模块的配置,Abp 本身提供的很多基础设施功能的一些在运行时的行为是通过很多不同的 Configuration 来开放给用 ...

  2. 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入

    使用react全家桶制作博客后台管理系统   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...

  3. ABP(现代ASP.NET样板开发框架)系列之5、ABP启动配置

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之5.ABP启动配置 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)” ...

  4. 基于DDD的.NET开发框架 - ABP启动配置

    返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...

  5. ABP启动配置

    ABP启动配置   返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行 ...

  6. ABP+AdminLTE+Bootstrap Table权限管理系统第三节--abp分层体系,实体相关及ABP模块系统

    返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 ABP模块系统 说了这么久,还没有详细说到abp框架,abp其实基于DDD(领域驱动设计)原则的细看分层如下: 再 ...

  7. abp 模块系统

    abp模块系统:ABP理论学习之模块系统 ABP提供了构建模块并将这些模块组合起来创建应用的基础设施.一个模块可以依赖另一个模块.一般来说,一个程序集可以认为是一个模块.一个模块是由一个派生了AbpM ...

  8. Magicodes.Pay,打造开箱即用的统一支付库,已提供ABP模块封装

    Magicodes.Pay,打造开箱即用的统一支付库,已提供ABP模块封装 简介 Magicodes.Pay,是心莱科技团队提供的统一支付库,相关库均使用.NET标准库编写,支持.NET Framew ...

  9. ABP(现代ASP.NET样板开发框架)系列之4、ABP模块系统

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之4.ABP模块系统 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)” ...

随机推荐

  1. MySQL性能优化-内存参数配置

    Mysql对于内存的使用,可以分为两类,一类是我们无法通过配置参数来配置的,如Mysql服务器运行.解析.查询以及内部管理所消耗的内存:另一类如缓冲池所用的内存等. Mysql内存参数的配置及重要,设 ...

  2. hdu 5895 Mathematician QSC 指数循环节+矩阵快速幂

    Mathematician QSC Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  3. Django中间件的总结

    一.中间件 --中间件是一个轻量级.底层的插件系统,可以加入Django的请求和响应过程,修改Django的输入和输出 --每一个中间件组件是一个独立的Python类,可以定义下面方法中的一个和多个 ...

  4. Python给数字前固定位数加零

    python中有一个zfill方法用来给字符串前面补0,非常有用 n = " s = n.zfill(5) " zfill()也可以给负数补0 n = "-123&quo ...

  5. 0.00-050613_boot.s

    ! boot.s ! ! It then loads the system at 0x10000, using BIOS interrupts. Thereafter ! it disables al ...

  6. print webpage

    使用浏览器打印网页时(A4纸)有一个固定的尺寸: 高级浏览器: width:700px height:1000px

  7. ural 2020 Traffic Jam in Flower Town(模拟)

    2020. Traffic Jam in Flower Town Time limit: 1.0 secondMemory limit: 64 MB Having returned from Sun ...

  8. c# 打开第三方软件(如:电脑自带看图软件)

    嘿嘿,直接上示例代码 /// <summary> /// 利用第三方软件浏览加工图纸 /// </summary> /// <param name="fileP ...

  9. 使用Intellij Idea打开项目不能显示树形目录

    按下列步骤操作:1. 关闭IDEA, 2.然后删除项目文件夹下的.idea文件夹3.重新用IDEA工具打开项目 Open...

  10. nginx负载均衡的简单实现

    负载均衡是我们大流量网站要做的一个东西,下面我来给大家介绍在Nginx服务器上进行负载均衡配置方法,希望对有需要的同学有所帮助哦. 负载均衡 先来简单了解一下什么是负载均衡,单从字面上的意思来理解就可 ...