正如你所说,你的两个个人AutoFac 本身支持这些要求。
- 构造函数参数的运行时解析可以使用以下方式实现参数化实例化 http://autofac.readthedocs.org/en/latest/resolve/relationships.html#parameterized-instantiation-func-x-y-b
- 特定服务实现的解析可以使用以下方式实现键控服务查找 http://autofac.readthedocs.org/en/latest/resolve/relationships.html#keyed-service-lookup-iindex-x-b
然而,似乎没有直接支持同时使用这两个结构。 IE。下列不起作用:
public enum ServiceType
{
ServiceA,
ServiceB
}
public class MyComponent
{
public MyComponent(Func<string, IIndex<ServiceType, IService> factory)
{
var service = factory("some_string")[ServiceType.ServiceA];
}
}
我的工作一直是将服务的解析移至每个服务实现的工厂。然后,其工作原理如下:
- 依赖于特定服务实现的组件采用 AutoFac 工厂委托,该委托解析为特定于所需服务实现的工厂
- 反过来,服务工厂依赖于 AutoFac 工厂委托,该委托知道如何从服务的(运行时)构造函数参数创建特定的服务实现
- 此方法使用本机 AutoFac 构造,并且在容器连接之外不依赖于 AutoFac。
这是一个粗略的例子。请注意,多个工厂可以简化为一个通用工厂 - 但为了清楚起见,我将其保留为原样:
服务实施
public enum ServiceType
{
NotSet,
ServiceA,
ServiceB
}
public interface IService
{
string DoWork();
}
public class ServiceA : IService
{
private readonly string _name;
public ServiceA(string name)
{
_name = name;
}
public string DoWork()
{
throw new NotImplementedException();
}
}
public class ServiceB : IService
{
private readonly string _name;
public ServiceB(string name)
{
_name = name;
}
public string DoWork()
{
throw new NotImplementedException();
}
}
服务工厂
public interface IServiceFactory
{
IService Create(string name);
}
public class ServiceAFactory : IServiceFactory
{
private readonly Func<string, ServiceA> _factory;
public ServiceAFactory(Func<string, ServiceA> factory)
{
_factory = factory;
}
public IService Create(string name)
{
return _factory(name);
}
}
public class ServiceBFactory : IServiceFactory
{
private readonly Func<string, ServiceB> _factory;
public ServiceBFactory(Func<string, ServiceB> factory)
{
_factory = factory;
}
public IService Create(string name)
{
return _factory(name);
}
}
服务注册
builder.RegisterType<ServiceA>().As<ServiceA>();
builder.RegisterType<ServiceB>().As<ServiceB>();
builder.RegisterType<ServiceAFactory>().Keyed<IServiceFactory>(ServiceType.ServiceA);
builder.RegisterType<ServiceBFactory>().Keyed<IServiceFactory>(ServiceType.ServiceB);
builder.RegisterType<ComponentWithServiceDependency>().As<ComponentWithServiceDependency>();
用法示例
public class ComponentWithServiceDependency
{
private readonly IService _service;
public ComponentWithServiceDependency(IIndex<ServiceType, IServiceFactory> serviceFactories)
{
// Resolve the ServiceB service implementation,
// using the string "test" as its constructor dependency
_service = serviceFactories[ServiceType.ServiceB].Create("test");
}
public string Test()
{
return _service.DoWork();
}
}