@romaro

Можно ли получить тип интерфейса, переданного в дженерик-метод и правильно ли использовать его таким способом?

В моем приложении есть сервис, который отвечает за печать этикеток. Всего несколько видов этикеток и для каждого свой набор параметров. Однако для некоторых этикеток параметры полностью совпадают. Я определил единственный универсальный метод для интерфейса сервиса:
public interface IPrintService
    {
        public void PrintLabel<T>(T labelParams) where T: IPrintService_AbstractLabelParams;
    }


И, соответственно, описал интерфейсы для объектов параметров каждого вида этикеток:
public interface IPrintService_AbstractLabelParams
    {
        string PrinterName { get; init; }
        int Copy { get; init; }
    }

    public interface IPrintService_OLabelParams : IPrintService_AbstractLabelParams
    {
        string ProductName { get; init; }
    }

    public interface IPrintService_WLabelParams : IPrintService_AbstractLabelParams
    {
        string ProductName { get; init; }
    }

    public interface IPrintService_IncomeProductLabelParams : IPrintService_AbstractLabelParams
    {
        public int ProductId { get; init; }
        public int Sku { get; init; }
    }


Теперь я реализую метод на уровне класса самого сервиса:
public class PrintService : IPrintService
    {
        public void PrintLabel<T>(T labelParams) where T : IPrintService_AbstractLabelParams
        {
            ...
        }
    }


Это метод-роутер, который, в зависимости от типа этикетки, должен вызывать соответствующий внутренний метод библиотеки принтера.

Но как мне определить тип этикетки?

Можно, конечно, добавить в IPrintService_AbstractLabelParams обязательное свойство LabelType и по его значению делать switch. Но наверняка существует способ получить значение типа интерфейса, который был передан в обобщенный метод. Оператор is тут не подойдет, т.к. для некоторых этикеток могут полностью совпадать параметры.

То есть насколько правильно (и возможно ли) использовать интерфейс в качестве сепаратора типа этикетки?
  • Вопрос задан
  • 107 просмотров
Решения вопроса 1
Ну ты можешь сделать так:
switch(parameter) {
  case IPrintService_IncomeProductLabelParams incomeProductLabel: {
    // ...
    break;
  }
  case IPrintService_WLabelParams wLabel: {
    // ...
    break;
  }
  // итд
  default:
    // ...
  break;
}

Но мне не понятен смысл женерика и интерфейсов с пропертями.
Ты собираешься делать параметры ещё и структурами?
В принципе тут можно избавиться от интерфейсов вообще и оставить только конкретные классы, а в IPrintService сделать несколько перегрузок, например.
Или сделать по интерфейсу для каждого типа этикеток.

Вообще, я у тебя тут вижу три разные вещи у этикеток:
1. Какой принтер используется (PrinterName)
2. Параметры задания на печать (Copy)
3. Параметры самой этикетки. Её тип и, например, SKU товара.
Попробуй подумать с этой стороны.
Например ты можешь сделать такой IPrinter, который будет принимать в себя PrintTask, у которого будет написано количество нужных копий и Payload который будет уже самой этикеткой.
Конкретная реализация IPrinter может быть привязана к одному физическому принтеру.

А Payload ты можешь формировать отдельно от сервиса печати. Например у тебя может быть какая-нибудь "служба шаблонов этикеток", в которую ты передаёшь объект с параметрами этикетки, а она отдаёт тебе уже сформированный объект этикетки, который пригоден для печати (Что там вообще принтер принимает? Картинку?)
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
freeExec
@freeExec
Участник OpenStreetMap
Тут то всё просто, кастуешь к интерфейсу и проверяешь получилось что или пусто.
Но в данном примере вообще не вижу какой либо выгоды от интерфейсов, если всё равно надо делать развилки руками.
Ответ написан
@crokocat
typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы