Разрешение многократной реализации интерфейса - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть приложение, которое имеет 3 службы:

  • Служба проверки, которая проверяет содержимое на основе типа
  • Служба боссов, которая преобразует данные в отношении людей-боссов
  • Служба сотрудников, которая конвертирует вещи в отношении сотрудников.

Выглядит это так упрощенно:

public interface IValidatorService<T>
{
    void ValidateContent(AbstractValidator<T> validator, List<T> content);
}

public class ValidatorService <T> : IValidatorService<T>
{
    public void ValidateContent(AbstractValidator<T> validator, List<T> peopleContent)
    { ...does its job...}
}

public interface IPeopleService<T>
{
    List<T> Convert(string json);
}

public class BossService : IPeopleService<People>
{
    IValidatorService<Boss> _validatorService;

    public BossService (IValidatorService<Boss> validatorService)
    {
        _validatorService = validatorService;
    }

    public List<People> Convert(string json)
    { ...does its job for boss...}
}

public class EmployeeService : IPeopleService<People>
{
    IValidatorService<Employee> _validatorService;

    public EmployeeService (IValidatorService<Employee> validatorService)
    {
        _validatorService = validatorService;
    }

    public List<People> Convert(string json)
    { ...does its job for employee...}
}

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

var serviceProvider = new ServiceCollection()
    .AddSingleton<IValidatorService<Boss>, ValidatorService<Boss>>()
    .AddSingleton<IPeopleService<People>, BossService>()
    .BuildServiceProvider();

var bosses = serviceProvider.GetService<IPeopleService<People>>().Convert(json);

Но на самом деле я хочу сделать что-то подобное, хотя моя проблема в том, как узнать, какую реализацию выполнить для начальника и для сотрудника соответственно, поскольку в данном случае они одного типа IPeopleService

var serviceProvider = new ServiceCollection()
    .AddSingleton<IValidatorService<Boss>, ValidatorService<Boss>>()
    .AddSingleton<IPeopleService<People>, BossService>()
    .AddSingleton<IValidatorService<Employee>, ValidatorService<Employee>>()
    .AddSingleton<IPeopleService<People>, EmployeeService>()
    .BuildServiceProvider();

var bosses = serviceProvider.GetService<IPeopleService<People>>().Convert(json);
var employees = serviceProvider.GetService<IPeopleService<People>>().Convert(json);

Ответы [ 2 ]

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

Вы не можете сделать это напрямую, используя встроенный контейнер.Вам нужно будет ввести фабрику, которая действует как посредник, и вместо этого ввести фабрику.Это позволяет вам указать дополнительный контекст для получения нужного сервиса (например, по имени).

Взгляните на GitHub repo и NuGet package для DependencyInjection.Extensions .

Это решение было вдохновлено вопросом о названном разрешении.

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

Это не так.В зависимости от того, какой механизм DI вы используете, это вызовет какое-то неоднозначное исключение разрешения, или некоторые реализации ламера могут занять первое.Некоторые другие даже позволяют вам получить все реализации IPeopleService через механизм IEnumerable.

И почему механизм DI знает, какой из них вы хотите?Вы не предоставили ему никакого контекста для принятия решения.

Вы должны будете сделать один IPeopleService и один IPeopleService .

РЕДАКТИРОВАТЬ: Kit делаетХороший вопрос ... некоторые движки DI поддерживают разрешение по имени или другим типам контекстов.

...