WedX - журнал о программировании и компьютерных науках

Как зарегистрировать и разрешить open generic с двумя аргументами типа в качестве интерфейса с одним аргументом типа с помощью Autofac

Проблема

У меня есть несколько конкретных универсальных классов с двумя аргументами типа, которые реализуют общий интерфейс с одним аргументом типа. Например:

public interface ISomeService<T>
{
    // ...
}

public class SomeService<TA, TB> : ISomeService<TA>
{
    // ...
}

Регистрирую их с помощью Autofac вот так:

var containerBuilder = new ContainerBuilder();

containerBuilder.RegisterGeneric(typeof(SomeService<,>))
    .As(typeof(ISomeService<>))
    .InstancePerLifetimeScope();

var container = containerBuilder.Build();

При попытке разрешить экземпляр ISomeService<Foo> следующим образом:

var service = container.Resolve<ISomeService<Foo>>();

Я получаю Autofac.Core.Registration.ComponentNotRegisteredException исключение о том, что запрошенная служба ISomeService`1[[Foo]] не зарегистрирована.

Вопросы

  1. То, что я пытаюсь сделать, невозможно с помощью Autofac?
  2. Если да, то есть ли обходной путь?
  3. Если нет, предлагают ли другие контейнеры DI такую ​​возможность, например SimpleInjector?

  • Как контейнер узнает тип TB? 06.10.2016
  • @YacoubMassad Хороший вопрос. Я подозревал, что в этом корень проблемы. Итак, как мне зарегистрировать службу без необходимости явно регистрировать каждый общий тип по отдельности (например, containerBuilder.RegisterType<SomeService<Foo, Bar>>().As<ISomeService<Foo>>()? 06.10.2016
  • Тип TB - это деталь реализации SomeService<TA, TB>, а не то, что я хотел бы передать в интерфейс ISomeService<T>. 06.10.2016
  • Все ли реализации имеют одинаковое значение для TB? 06.10.2016
  • @ Стивен - Нет, к сожалению, нет. На самом деле TA и TB являются интерфейсом модели предметной области и сущностью структуры сущности соответственно. Между ними существует прямое (и уникальное) отображение, например SomeService<IPerson, PersonEntity>. Часть сущности структуры сущности - это то, что я не хочу просачиваться на свой бизнес-уровень, где все должно быть в терминах объектов модели предметной области, например IPerson. 07.10.2016
  • Если можно описать эту взаимосвязь в ограничении типа (например, class SomeService<TA, TB> where TA : IEntity<TB>), в этом случае регистрация, такая как container.Register(typeof(ISomeService<>), typeof(SomeService<,>)), будет работать, как в Simple Injector. В противном случае вам придется явно указывать каждое сопоставление. 07.10.2016
  • @Steven - Нет, нет никакой связи между моделью и классом сущности, которая может быть определена с помощью ограничения общего типа (я мог бы заставить его, но это было бы несколько надумано). 10.10.2016

Ответы:


1

С помощью Simple Injector вы можете зарегистрировать частично закрытый универсальный тип следующим образом:

container.Register(typeof(ISomeService<>),
    typeof(SomeService<,>).MakeGenericType(
        typeof(SomeService<,>).GetGenericArguments().First(),
        typeof(Bar)),
    Lifestyle.Scoped);

Нет другой библиотеки DI, которая могла бы справиться с этим, но в этом случае есть простой обходной путь для таких контейнеров, как Autofac; вы можете просто получить от типа:

public class BarSomeService<TA> : SomeService<TA, Bar>
{
    public BarSomeService([dependencies]) : base([dependencies]) { }
}

containerBuilder.RegisterGeneric(typeof(BarSomeService<>))
    .As(typeof(ISomeService<>))
    .InstancePerLifetimeScope();
06.10.2016
  • Наследование типа - интересный обходной путь, поэтому спасибо за предложение. Однако я не уверен, что это предпочтительнее явной регистрации каждого сопоставления. И если я правильно понимаю, первый из приведенных выше фрагментов кода все равно потребует явной регистрации для каждого сопоставления (т.е. typeof(Bar) выше). Еще раз спасибо за ваши мысли и идеи. Кстати, Simple Injector действительно впечатляет! 10.10.2016
  • Новые материалы

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..


    Для любых предложений по сайту: [email protected]