CCI正在编写外观以从不同来源获取数据,对其进行规范化和格式化。我是使用asp.net 5的新手,可以随意进行依赖注入,但是遇到了问题。我想知道如何根据运行时输入解析依赖关系。基于路由,我想实例化正确的存储库。例如,如果我通过了Toyota,我想实例化一个ToyotaRepository,如果我通过福特,我想实例化一个FordRepository。这些存储库还具有每个存储库唯一的依赖项。所有存储库共享相同的ICarRepository接口,并且依赖于相同的接口,但具有不同的具体实现。我曾考虑过使用工厂来创建存储库,但是每个存储库的依赖项都必须注入工厂,这感觉并不对。随着存储库数量的增加,需要注入的依赖项数量也随之增加。目前,我只是在工厂中更新存储库及其依赖项,这也感觉不对,不是很可靠。也许我的体系结构有问题?
[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来简化工作。任何帮助或评论将是一个很大的帮助。
最佳答案
使用注入所有存储库的工厂是可行的方法(并且比临时的“新建”依赖项要好得多)
例
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;
}
}