项目
版本

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文档

在本文档中