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;
    }
}

10-02 07:39
查看更多