您的位置:首页 > 其它

Autofac官方文档(十九)【模块】

2017-12-14 23:21 211 查看

介绍

IoC使用组件作为应用程序的基本构建块。提供对组件的构造函数参数和属性的访问通常被用作实现部署时配置的手段。

这通常是一个可疑的做法,原因如下:

构造函数可以改变:对构造函数签名或组件属性的更改可能会中断部署的
App.config
文件 - 这些问题在开发过程中可能会出现很晚。

JSON/XML
难以维护:大量组件的配置文件可能难以维护。

“代码”开始在配置中显示:暴露类的属性和构造函数参数是对应用程序内部的“封装”的不愉快违反 - 这些细节不属于配置文件。

这是模块可以帮助的地方。

模块是一个小的类,可以用来捆绑“外观”背后的一组相关组件,以简化配置和部署。该模块公开了一组故意的,有限的配置参数,这些参数可以独立于用于实现模块的组件而改变。

模块中的组件仍然使用
组件/服务
级别的依赖关系来访问其他模块的组件。

模块本身不通过依赖注入。它们用来配置容器,它们并没有像其他组件那样实际注册和解析。例如,如果您的模块需要构造函数参数,则需要自行传递该参数。它不会来自容器。

模块的优点

降低配置复杂性

通过IoC配置应用程序时,通常需要在多个组件之间设置参数。模块将相关配置项目组合到一个地方,以减轻查找正确组件的负担。

模块的实现者确定模块的配置参数如何映射到组件的属性和构造器参数。

配置参数是显式的

通过组件直接配置应用程序会创建一个大的表面区域,在升级应用程序时需要考虑。当可以通过配置文件来设置潜在的任何属性时,每个站点的配置文件都不一样,重构就不再安全。

创建模块限制了用户可以配置的配置参数,并使维护程序员明确了这些参数。

你也可以避免在一个好的程序元素和一个好的配置参数之间取舍。

内部应用程序体系结构的抽象

通过组件配置应用程序意味着配置需要根据诸如使用枚举与创建策略类之类的事情而有所不同。使用模块隐藏应用程序结构的这些细节,保持配置简洁。

更好的类型安全

当组成应用程序的类可能因部署而异时,类型安全性的小幅降低总是存在的。然而,通过XML配置注册大量的组件会加剧这个问题。

模块是以编程方式构建的,因此可以在编译时检查其中的所有组件注册逻辑。

动态配置

配置模块内的组件是动态的:模块的行为可以根据运行时环境而变化。纯粹的基于组件的配置,即使可能,也是如此难。

高级扩展

模块不仅可以用于简单的类型注册,还可以附加到组件解析事件,并扩展参数的解析方式或执行其他扩展。 log4net集成模块示例显示了一个这样的模块。

示例

在Autofac中,模块实现了
Autofac.Core.IModule
接口。 通常他们将从
Autofac.Module
抽象类派生。

该模块提供了
IVehicle
服务:

public class CarTransportModule : Module
{
public bool ObeySpeedLimit { get; set; }

protected override void Load(ContainerBuilder builder)
{
builder.Register(c => new Car(c.Resolve<IDriver>())).As<IVehicle>();

if (ObeySpeedLimit)
builder.Register(c => new SaneDriver()).As<IDriver>();
else
builder.Register(c => new CrazyDriver()).As<IDriver>();
}
}


封装的配置

我们的
CarTransportModule
提供了
ObeySpeedLimit
配置参数,而没有暴露出这是通过在一个理智的或疯狂的驱动程序之间进行选择来实现的。 使用该模块的客户可以通过声明他们的意图来使用它:

builder.RegisterModule(new CarTransportModule() {
ObeySpeedLimit = true
});


或者在
Microsoft.Extensions.Configuration
配置格式中:

{
"modules": [{
"type": "MyNamespace.CarTransportModule, MyAssembly",
"properties": {
"ObeySpeedLimit": true
}
}]
}


这是非常有价值的,因为模块的实现可能会变化而没有流动的效果。 毕竟这就是封装的想法。

灵活性覆盖

虽然
CarTransportModule
的客户端可能主要关注
IVehicle
服务,但是该模块也会将其
IDriver
依赖关系注册到容器中。 这确保了配置仍然能够在部署时被覆盖,就像组成模块的组件已经被独立注册一样。

在编程配置之后使用
Autofac
添加XML配置时,这是一个“最佳实践”,例如:

builder.RegisterModule(new CarTransportModule());
builder.RegisterModule(new ConfigurationSettingsReader());


通过这种方式,可以在配置文件中创建“emergency”覆盖:

{
"components": [{
"type": "MyNamespace.LearnerDriver, MyAssembly",
"services": [{
"type": "MyNamespace.IDriver, MyAssembly"
}]
}]
}


所以,模块增加了封装,但是并不排除你必须修补它们的内部。

适应部署环境

模块可以是动态的 - 也就是说,他们可以将自己配置到自己的执行环境中。

当一个模块被加载时,它可以做很多漂亮的事情,比如检查环境:

protected override void Load(ContainerBuilder builder)
{
if (Environment.OSVersion.Platform == PlatformID.Unix)
RegisterUnixPathFormatter(builder);
else
RegisterWindowsPathFormatter(builder);
}


模块的常见用例

配置提供子系统的相关服务,例如 用NHibernate进行数据访问

将可选应用程序功能打包为“插件”

提供与系统整合的预编译包,例如 一个账号系统

注册许多经常一起使用的类似服务,例如 一组文件格式转换器

用于配置容器的新的或定制的机制,例如
JSON/XML
配置是使用模块实现的; 可以通过这种方式添加使用属性的配置
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: