Autofac 命名和键控服务
Autofac 提供了三种常见的服务标识方法。最常见的就是按类型识别:
builder.RegisterType<OnlineState>().As<IDeviceState>();
在这个例子中,将 IDeviceState
类型的 OnlineState
组件关联起来。你可以使用 Resolve()
方法通过服务类型获取组件实例:
var r = container.Resolve<IDeviceState>();
然而,你也可以通过字符串名称或对象键来识别服务。
命名服务
使用服务名称可以进一步标识服务。在这种情况下,Named()
注册方法取代了 As()
。
builder.RegisterType<OnlineState>().Named<IDeviceState>("online");
要获取命名服务,可以使用 ResolveNamed()
方法:
var r = container.ResolveNamed<IDeviceState>("online");
命名服务实际上就是使用字符串作为键的键入服务,因此接下来描述的技术同样适用于命名服务。
键控服务
在某些情况下,使用字符串作为组件名称很方便,但在其他情况下我们可能希望使用其他类型的键。键入服务提供了这种能力。
例如,在我们的示例中,枚举可能描述设备的不同状态:
public enum DeviceState { Online, Offline }
每个枚举值对应于服务的一个实现:
public class OnlineState : IDeviceState { }
然后可以像下面这样使用枚举值作为实现的键进行注册。
var builder = new ContainerBuilder();
builder.RegisterType<OnlineState>().Keyed<IDeviceState>(DeviceState.Online);
builder.RegisterType<OfflineState>().Keyed<IDeviceState>(DeviceState.Offline);
// 在这里注册其他组件
显式解析
可以使用 ResolveKeyed()
显式解析键入服务:
var r = container.ResolveKeyed<IDeviceState>(DeviceState.Online);
但这会导致使用容器作为服务定位器,这是不推荐的。为了替代这种模式,Autofac 提供了 IIndex
类型。
使用索引解析
Autofac.Features.Indexed.IIndex<K, V>
是 Autofac 自动实现的一种关系类型<../resolve/relationships>。根据键选择服务实现的组件可以通过接受一个类型为 IIndex<K, V>
的构造函数参数来做到这一点。
public class Modem : IHardwareDevice
{
IIndex<DeviceState, IDeviceState> _states;
IDeviceState _currentState;
public Modem(IIndex<DeviceState, IDeviceState> states)
{
_states = states;
SwitchOn();
}
void SwitchOn()
{
_currentState = _states[DeviceState.Online];
}
}
在 SwitchOn()
方法中,使用索引来查找注册时使用 DeviceState.Online
键的 IDeviceState
实现。
使用属性解析
Autofac 的 metadata特性 提供了一个 KeyFilterAttribute
,允许你标记带有指定键应使用的键入服务的构造函数参数。该属性的用法如下:
public class ArtDisplay : IDisplay
{
public ArtDisplay([KeyFilter("Painting")] IArtwork art) { ... }
}
当你注册需要属性过滤的组件时,需要确保启用它。查询属性并执行过滤操作会带来轻微但非零的性能开销,所以它不会自动发生。
var builder = new ContainerBuilder();
builder.RegisterType<Painting>().Keyed<IArtwork>("Painting");
builder.RegisterType<ArtDisplay>().As<IDisplay>().WithAttributeFiltering();
有关如何使用属性和过滤的更多信息,请参阅 metadata文档 。