Правильный способ получить правильную реализацию того же интерфейса - PullRequest
0 голосов
/ 09 мая 2018

Имейте в виду, что я не собираюсь добавлять дополнительные зависимости, если мне это не нужно. Кроме того, большинство идей уже отсюда (stackoverflow.com), которые я нашел при поиске решения.

Допустим, у меня есть интерфейс IPrinterRepository, для которого у меня есть несколько различных реализаций.

Например EpsonRepository реализует IPrinterRepository, как и CanonRepository, HPRepository и многие другие

Итак, теперь я зарегистрировал свои службы в ConfigurationServices вот так

services.AddTransient<EpsonRepository>();
services.AddTransient<HPRepository>();
services.AddSingleton<IPrinterRepositoryResolver, PrinterRepositoryResolver>();

- V1 -

На данный момент я сохраняю PRINTER_CODE в своей БД для каждого активного принтера, активированного определенным пользователем. PrinterCode - это класс константных строк.

PrinterRepositoryResolver обрабатывает выбор правильной реализации. Так что есть метод, который делает это с помощью оператора switch.

public IPrinterRepository GetRepository(string key)
{   
    switch (key)
    {
        case PrinterCode.Epson:
            return (IPrinterRepository)_serviceProvider.GetService(typeof(EpsonRepository));
        case PrinterCode.HP:
            return (IPrinterRepository)_serviceProvider.GetService(typeof(HPRepository));
        default:
            throw new KeyNotFoundException("Sevice not implemented or not supported any more!");
    }
}

- V2 -

Или, может быть, я могу выбрать правильную реализацию по типу, чтобы мне не приходилось использовать PRINTER_CODE или поддерживать оператор switch. Пример * * тысяча двадцать пять

Вместо PRINTER_CODE, сохраняя полное имя реализации в БД в виде строки и используя ее для выбора правильной реализации позже, когда это необходимо.

public IPrinterRepository GetRepository(string ImplementationName)
{
    var repoType= Type.GetType(ImplementationName);
    return (IPrinterRepository)_serviceProvider.GetService(repoType);
}

Это все работает в моей среде разработки, но я не знаю, нормально ли это.

Лично мне не нравится переключатель, потому что кто-то должен будет поддерживать коды принтеров и переключатель каждый раз, когда добавляется новая реализация принтера.

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

1 Ответ

0 голосов
/ 09 мая 2018

Я бы пошел слегка измененным путем V1:

Объект, получающий шаблон, исключается, и тип объекта не связан с его именем, как в случае V2.

public IPrinterRepository GetRepository(string name)
{
    if (!_PrinterTypes.TryGetValue(name, out var type))
        throw new KeyNotFoundException("Sevice not implemented or not supported any more!");

    return _serviceProvider.GetService(type);
}

static readonly Dictionary<string, Type> _PrinterTypes = new Dictionary<string, Type>
{
    [PrinterCode.Epson] = typeof(EpsonRepository),
    [PrinterCode.HP] = typeof(HPRepository)
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...