Использование IoC с внутренними объектами

2

В настоящее время я пишу SDK с открытым исходным кодом для используемой программы, и я использую контейнер IoC внутри (NInject) для подключения всех моих внутренних зависимостей.

У меня есть некоторые объекты, которые помечены как внутренние, так что я не толпию публичный API, поскольку они используются только внутренне и не должны рассматриваться пользователем, как фабрики и другие объекты. Проблема, с которой я сталкиваюсь, заключается в том, что NInject не может создавать внутренние объекты, что означает, что я должен отметить все мои внутренние объекты public, которые объединяют публичный API.

Мой вопрос: есть ли способ обойти эту проблему, или я все делаю неправильно?

PS. Я думал об использовании InternalsVisiableTo атрибута, но я чувствую, что это немного запах.

  • 0
    Если это SDK с открытым исходным кодом, мне интересно, почему вы пытаетесь предотвратить использование вашего кода? Я понимаю, что если вы пытаетесь убедиться, что мы, "пользователи" SDK, не создаем экземпляры объектов неправильно, но для меня это еще более неприятный запах (SRP, LSP). Можете ли вы объяснить больше ваших ограничений?
Теги:
inversion-of-control
ninject

5 ответов

3
Лучший ответ

Быстрый просмотр других ответов: не похоже, что вы делаете что-то настолько отличное, что в Ninject есть что-то принципиально неправильное, что вам нужно будет изменить или заменить его. Во многих случаях вы не можете "пойти прямо на [внутренности]", потому что они полагаются на неразрешенную инъекцию зависимостей; следовательно, использование Ninject в первую очередь. Также похоже, что у вас уже есть внутренний набор интерфейсов, поэтому вопрос был задан.

Мысли: одна проблема с использованием Ninject непосредственно в вашем SDK или библиотеке заключается в том, что тогда вашим пользователям придется использовать Ninject в своем коде. Это, вероятно, не проблема для вас, потому что это ваш выбор IoC, чтобы вы все равно использовали его. Что делать, если они хотят использовать другой контейнер IoC, то теперь у них есть фактически два дублирующих действия. Хуже того, что, если они хотят использовать Ninject v2, и вы использовали v1.5, то это действительно усложняет ситуацию.

Лучший случай:, если вы можете реорганизовать свои классы таким образом, чтобы они получали все, что им нужно, через Injection Dependency, тогда это самое чистое, потому что для кода библиотеки не нужен контейнер IoC. Приложение может подключаться к зависимостям, и оно просто течет. Однако это не всегда возможно, так как иногда библиотечным классам необходимо создавать экземпляры, у которых есть зависимости, которые вы не можете разрешить посредством инъекции.

Предложение: CommonServiceLocatorадаптер Ninject для него) были специально разработаны для этой ситуации (библиотеки с зависимостями). Вы кодируете CommonServiceLocator, а затем приложение указывает, какие DI/IoC фактически поддерживают интерфейс.

Это немного боль в том, что теперь у вас должен быть Ninject и CommonServiceLocator в вашем приложении, но CommonServiceLocator довольно легкий. В коде SDK/библиотеки используется только CommonServiceLocator, который довольно чист.

0

Я собираюсь голосовать за решение InternalsVisibleTo. На самом деле это не запах. Точка атрибута заключается в том, чтобы разрешить поведение, которое вы хотите, вместо того, чтобы прыгать через всевозможные сложные обручи, чтобы заставить все работать без него, просто используйте функциональные возможности, предоставляемые средой для решения этой конкретной проблемы.

Я также предложил бы, если вы хотите скрыть свой выбор контейнера от пользователя, используя ILMerge, чтобы объединить сборки Ninject с вашим SDK и примените аргумент /internalize, чтобы изменить видимость сборок сборки Ninject на внутренние, поэтому пространства имен Ninject не вытекаются из вашей библиотеки (извините, не удалось найти ссылку на документы ILMerge в Интернете, но есть файл документа в загрузке). Существует также хорошая запись в блоге об интеграции ILMerge в ваш процесс сборки.

0

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

0

Вы можете

  • изменить Ninject
  • выберите другой контейнер
0

Думаю, тебе это даже не нужно. IoC предназначен для общественных работ. Идите прямо к внутренним.

Но - это просто моя интуиция...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню