ABP可以在启动的时候对模块进行配置。
配置ABP
在模块的PreInitialize方法中,可以对ABP进行配置。配置示例如下:
public class SimpleTaskSystemModule : AbpModule
{
public override void PreInitialize()
{
//Add languages for your application
Configuration.Localization.Languages.Add(new LanguageInfo("en", "English", "famfamfam-flag-england", true));
Configuration.Localization.Languages.Add(new LanguageInfo("tr", "Türkçe", "famfamfam-flag-tr"));
//Add a localization source
Configuration.Localization.Sources.Add(
new XmlLocalizationSource(
"SimpleTaskSystem",
HttpContext.Current.Server.MapPath("~/Localization/SimpleTaskSystem")
)
);
//Configure navigation/menu
Configuration.Navigation.Providers.Add<SimpleTaskSystemNavigationProvider>();
}
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}
ABP是模块化设计,不同的模块都可以对ABP进行配置。例如不同的模块可以通过添加不同的导航提供者来在主菜单上添加自己的菜单项。
替换内置服务
Configuration.ReplaceService 方法可以用来重写ABP中的内置服务。例如,你可以自己实现一个管理会话的服务(MySession), 然后使用Configuration.ReplaceService来替换掉ABP中内置的会话服务。
Configuration.ReplaceService<IAbpSession, MySession>(DependencyLifeStyle.Transient);
ReplaceService有一个重载方法,可以通过传递action参数来实现自定义替换。例如使用自定义的DbPerTenantConnectionStringResolver来替换IConnectionStringResolver, 代码如下:
Configuration.ReplaceService(typeof(IConnectionStringResolver), () =>
{
IocManager.Register<IConnectionStringResolver, DbPerTenantConnectionStringResolver>(DependencyLifeStyle.Transient);
});
一个服务可以被替换多次,这种情况在不同的模块中比较容易出现(例如服务A在模块A中被替换了一次,在模块B中又被替换了一次)。那么最后一次被替换的服务才是会被正确使用的服务,哪一个服务是最后一次被替换的服务,则是通过模块依赖的加载顺序来可确定。
配置模块
除了ABP框架自身提供的启动配置外,模块也可以通过扩展IAbpModuleConfigurations 接口提供自己的配置。
public static class AbpWebConfigurationExtensions
{
public static IAbpWebCommonModuleConfiguration AbpWebCommon(this IModuleConfigurations configurations);
}
...
using Abp.Web.Configuration;
...
public override void PreInitialize()
{
Configuration.Modules.AbpWebCommon().SendAllExceptionsToClients = true;
}
...
在上面的示例中,我们先通过AbpWebCommon扩展方法对IModuleConfigurations接口进行了扩展,接着在模块的PreInitialize方法中配置AbpWebCommon模块,将所有的异常信息都发送给客户端。
为模块创建配置
假设我们定义了一个MyModule的模块,这个模块有一些配置属性,那么第一步,我们可以为这些配置属性创建一个类
public class MyModuleConfig
{
public bool SampleConfig1 { get; set; }
public string SampleConfig2 { get; set; }
}
接着我们可以在模块的PreInitialize 方法中,通过依赖除注入注册这个配置类,这样它就可以被注入了。
IocManager.Register<MyModuleConfig>();
如上代码所示,配置类应该被注册为单实例的。注册后,我们就可以对MyModule模块进行配置了:
Configuration.Get<MyModuleConfig>().SampleConfig1 = false;
上述代码中,直接使用了Configuration.Get
public static class MyModuleConfigurationExtensions
{
public static MyModuleConfig MyModule(this IModuleConfigurations moduleConfigurations)
{
return moduleConfigurations.AbpConfiguration.Get<MyModuleConfig>();
}
}
改进后,其他模块就可以通过扩展方法来配置MyModule了:
Configuration.Modules.MyModule().SampleConfig1 = false;
Configuration.Modules.MyModule().SampleConfig2 = "test";
改进后的这种方法,可以非常容易的知道有哪些模块配置,并且提供一个统一的访问入口(Configuration.Modules...)。ABP内置的模块配置也是通过这种扩展方法的方式来实现的。
设置了配置信息后,如果模块中的其他服务需要获取模块配置信息(MyModuleConfig),我们可以注入MyModuleConfig,接着就可以使用了。
public class MyService : ITransientDependency
{
private readonly MyModuleConfig _configuration;
public MyService(MyModuleConfig configuration)
{
_configuration = configuration;
}
public void DoIt()
{
if (_configuration.SampleConfig2 == "test")
{
//...
}
}
}
通过这种方方式,ABP就可以对模块就行集中的配置管理了。在统一的地方进行模块的配置设置,在需要使用的地方通过注入的方式来获取配置的值。