CCI正在编写一个外观来获取来自不同来源的数据,对其进行规范化和格式化。我是新手使用asp.net 5并给出依赖注入,但我遇到了问题。我想知道如何根据运行时输入解决依赖关系。基于我想要实例化正确的存储库的路由。例如,如果我通过丰田我想要实例化一个ToyotaRepository,如果我通过福特我想要实例化一个FordRepository。这些存储库还具有每个存储库唯一的依赖项。所有存储库共享相同的ICarRepository接口,并且依赖于相同的接口但具体实现不同。我想过使用工厂来创建存储库,但是每个存储库的依赖关系必须注入工厂,这感觉不对。随着存储库数量的增加,需要注入的依赖项数量也随之增加。目前我只是在工厂中新建了存储库及其依赖项,这也感觉不对,不是非常SOLID。也许我的架构存在问题?
[Route("api/v1/[controller]")]
public class CarsController : Controller
{
private IDataFormatter<Product> _formatter;
private ILogger _logger;
private ICarRepositoryFactory _repositoryFactory;
public CarssController(ILogger<CarsController> logger, IProductRepositoryFactory repositoryFactory, IDataFormatter<Car> formatter)
{
_logger = logger;
_repositoryFactory = repositoryFactory;
_formatter = formatter;
}
[HttpGet("{carType}")]
public async Task<IEnumerable<Car>> GetCars(string carType)
{
var repository = _repositoryFactory.Create(carType);
var cars = await repository.GetAll();
foreach(var car in cars)
{
_formatter.Format(car);
}
return cars;
}
}
public class CarRepositoryFacotry : ICarRepositoryFactory
{
private Dictionary<string, Func<ICarRepository>> _carRepositories = new Dictionary<string, Func<ICarRepository>>();
private ILogger<ICarRepository> _logger;
private IOptions<WebOptions> _webOptions;
private IOptions<DisplayInfoOptions> _displayOptions;
public CarRepositoryFacotry(ILogger<ICarRepository> logger, IOptions<WebOptions> webOptions, IOptions<DisplayInfoOptions> displayInfoOptions)
{
_logger = logger;
_webOptions = webOptions;
_displayInfoOptions = displayInfoOptions;
_carRepositories.Add("toyota", () => new ToyotaRepository(_logger, new DisplayInfoRepository(_displayInfoOptions), new ToyotaMapper(), _options));
_carRepositories.Add("ford", () => new FordRepository(_logger, new DisplayInfoRepository(_displayInfoOptions), new FordMapper(), _options));
}
public ICarRepository Create(string carType)
{
Func<ICarRepository> repo;
_carRepositories.TryGetValue(carType, out repo);
return repo.Invoke();
}
}
我目前正在使用asp.net 5中的内置依赖框架,但我愿意使用autofac,如果它让事情变得更有效。任何帮助或评论都会有很大的帮助。
答案 0 :(得分:1)
使用工厂注入所有存储库是可行的方法(并且比临时&#34;新的&#34;依赖性更好)
示例强>
public interface IVehicleRepository
{
bool CanHandle(string vendor); // example how to deal with choosing appropriate repository
IEnumerable<Vehicle> GetAll();
}
public class VehicleFactory
{
private readonly IVehicleRepository[] repositories;
public VehicleFactory(IVehicleRepository[] repositories)
{
this.repositories = repositories;
}
public IVehicleRepository Create(string vendor) {
return repositories.Single(r => r.CanHandle(vendor));
}
}
<强>用法:强>
[Route("api/v1/[controller]")]
public class CarController : Controller
{
private readonly VehicleFactory factory;
public CarController(VehicleFactory factory)
{
this.factory = factory;
}
[HttpGet("{vehicleType}")]
public IEnumerable<Vehicle> GetVehicles(string vehicleType)
{
var repository = factory.Create(vehicleType);
var vehicles = repository.GetAll();
foreach (var vehicle in vehicles)
{
// Process(vehicle)
}
return vehicles;
}
}
答案 1 :(得分:0)
我是这样看的:
Google的第一个链接。可能不是最好的,但很好。
http://www.codeproject.com/Articles/560798/ASP-NET-MVC-Controller-Dependency-Injection-for-Be
答案 2 :(得分:0)
我的团队使用 Castle Windsor,这是一个 IoC 容器,可以轻松解决我们的所有依赖项。 (应该类似于 Autofac,但我在企业应用中更常看到 Castle Windsor)
在你的情况下,你可以
1.像这样注册 FordRepository
:
public class RepositoriesInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Classes.FromThisAssembly(),
Component.For<DisplayInfoRepository>().ImplementedBy<DisplayInfoRepository>
.DependsOn(Dependency.OnValue("_displayInfoOptions", displayInfoOptionsObject)),
// whatever property name you have in DisplayInfoRepository
Component.For<ICarRepository>().ImplementedBy<FordRepository>().Named("Ford")
.DependsOn(Dependency.OnComponent(typeof(Logger), nameof("Logger")))
.DependsOn(Dependency.OnComponent(typeof(DisplayInfoRepository), nameof(DisplayInfoRepository)))
.DependsOn(Dependency.OnComponent(typeof(FordMapper), nameof(FordMapper)))
.DependsOn(Dependency.OnValue("_option", optionObject)),
// what ever property name you have in FordRepository
);
}
}
2.启动容器:
// application starts...
var container = new WindsorContainer();
container.Install(FromAssembly.This());
// clean up, application exits
container.Dispose();
3.根据字符串获取您的汽车存储库 像这样
var carRepo = container.Resolve<ICarRepository>("Ford");
如果有任何问题,请告诉我!不胜感激!