我对构建依赖项的正确方法有疑问。
想象一下,您有一个Web api控制器,它具有一个带有两个参数的单独方法:id和bar。 控制器需要读取基于“ id”值的特定配置,并向应用了该配置的其他服务发出请求。
public class FooController : ApiController
{
private readonly IConfigurationProvider _configurationProvider;
private readonly IService _service;
public FooController(IConfigurationProvider configurationProvider, IService service)
{
_configurationProvider = configurationProvider;
_service = service;
}
public IHttpActionResult Bar(int id, int bar)
{
var configuration = _configurationProvider.GetConfiguration(id);
_service.Configure(configuration);
var barResult = _service.Bar(bar);
return Ok(barResult);
}
}
我不太确定我在依赖注入方面是否做对了:
从依赖注入的角度来看,此示例中还有其他问题吗?
谢谢。
答案 0 :(得分:1)
您可以尝试工厂类(构建器类可能是错误的事情)
public class ServiceFactory : IServiceFactory
{
private readonly Dictionary<int, IService> _services = new Dictionary<int, IService>();
private readonly IConfigurationProvider _configurationProvider;
public ServiceFactory(IConfigurationProvider configurationProvider)
{
_configurationProvider = configurationProvider;
}
public IService GetService(int id)
{
if (!_services.ContainsKey(id))
{
var config = _configurationProvider.GetConfiguration(id);
var service = new Service(config);
_services.Add(id, service);
}
return _services[id];
}
}
这将创建服务的实例,并在工厂类的生存期内保留对它的引用,因此只需创建一次即可。然后注册ServiceFactory并将其注入到您的控制器中。
public class FooController : ApiController
{
private readonly IServiceFactory _serviceFactory;
public FooController(IServiceFactory serviceFactory)
{
_serviceFactory = serviceFactory;
}
public IHttpActionResult Bar(int id, int bar)
{
var service = _serviceFactory.GetService(id);
var barResult = service.Bar(bar);
return Ok(barResult);
}
}
现在您的控制器仍然可以测试,您不必担心被调用Configure(),因为'id'是对服务构造函数的依赖。
P.S。不尊重@Ahmed Sherien,但不要使用Unity,它又旧又慢!!! ;-)
答案 1 :(得分:0)
在这种情况下,我将使用键控解决方案...如果您使用的是团结,则类似这样:
IUnityContainer container = new UnityContainer();
container.RegisterType<IConfiguration, ConfigurationType1>("Type1");
container.RegisterType<IConfiguration, ConfigurationType2>("Type2");
IConfiguration cfg1 = container.Resolve<IConfiguration>("Type1"); // return ConfigurationType1 object
IConfiguration cfg2 = container.Resolve<IConfiguration>("Type2"); // return ConfigurationType2 object
在您的情况下,实现将如下所示:
public class FooController : ApiController
{
private readonly IService _service;
public FooController(IService service)
{
_service = service;
}
public IHttpActionResult Bar(int id, int bar)
{
var configuration = container.Resolve<IConfiguration>(id.ToString());
_service.Configure(configuration);
var barResult = _service.Bar(bar);
return Ok(barResult);
}
}