Внедрение зависимостей в веб-API - PullRequest
0 голосов
/ 31 октября 2018

У меня вопрос о правильном способе структурирования зависимостей.

Представьте, что у вас есть контроллер веб-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);
        }
}

Я не совсем уверен, что я делаю это правильно с точки зрения внедрения зависимости:

  • Сервис инициализируется в конструкторе, но конфигурация неизвестно, пока запрос не будет выполнен. Клиент сервиса может не вызывать Configure, и это может вызвать проблемы ( работы шаблона Builder здесь? ).
  • Должна ли сама служба заботиться о загрузке конфигурации?

Есть ли другие проблемы в этом примере с точки зрения внедрения зависимостей?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 01 ноября 2018

Вы можете попробовать фабричный класс (класс строителя, вероятно, неправильный)

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, он старый и медленный !!! ; -)

0 голосов
/ 01 ноября 2018

В этих случаях я бы использовал ключевое разрешение ... что-то вроде этого, если вы используете единство:

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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...