Подтвердить что ты не робот

Зачем использовать сторонний DI-контейнер поверх встроенного ASP.NET Core DI-контейнера?

Поскольку в настоящее время не хватает документации по теме DI - Dependency Injection. Каковы плюсы/минусы использования встроенного DI поверх существующих решений, таких как (Ninject, Autofac, StructureMap)? И каковы текущие ограничения внедрения зависимостей по умолчанию (если есть)?

Кроме того, может ли кто-нибудь помочь мне понять, в чем разница между этими регистрациями?

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IService, Service>();
    services.AddScoped<IService, Service>();
    services.AddSingleton<IService, Service>();
    services.AddInstance(service);
}
4b9b3361

Ответ 1

Контейнер .NET Core DI не подходит для разработки любого приложения разумного размера, которое использует слабую связь и следует принципам SOLID, потому что:

  • Это не поможет вам в проверке вашей конфигурации, что очень затруднит диагностику проблем, возникающих из-за общих неправильных настроек. В приложениях разумного размера на самом деле довольно сложно обнаружить эти ошибки самостоятельно.
  • Нельзя применять сквозные проблемы с использованием перехватчиков или декораторов в удобной для обслуживания форме. Это делает обслуживание любого приложения разумного размера действительно дорогим.
  • Хотя он поддерживает отображение открытых обобщенных абстракций в открытые универсальные реализации, его реализация довольно наивна и не может работать с универсальными типами с ограничениями типов, более сложными сопоставлениями универсальных типов и дисперсией.
  • Невозможно сделать условную/контекстную регистрацию таким образом, чтобы при использовании Auto-Wiring регистрации вводились только определенному кругу потребителей. например при наличии двух компонентов Service1 и Service2, которые оба зависят от ILogger, вы можете ввести Service1 с помощью NullLogger и Service2 с помощью FileLogger, или вы хотите, чтобы Service1 вводили с помощью Logger<Service1> и Service2 с Logger<Service2>.

Основная причина существования этих ограничений заключается в том, что целью встроенного контейнера является предоставление возможностей DI особенно самой платформе при сохранении минимального набора его функций в надежде, что более зрелые контейнеры DI смогут интегрироваться с этим. Другими словами, он пытается действовать как наименьший общий знаменатель (ЖК). Благодаря функции ЖК-дисплея он никогда не сможет превратиться в полноценный DI-контейнер, который будет полезен для разработки приложений (не нарушая обещание быть ЖК-дисплеем).

Если вы начинаете с нового и простого проекта, я советую применить Pure DI (что означает компоненты с ручной проводкой внутри Composition Root без использования контейнера) и разрешить ваши типы с помощью подключите свой собственный IControllerActivator. Позже, когда такие функции, как авторегистрация и перехват, улучшат удобство обслуживания вашего корня композиции, переключитесь на одну из установленных библиотек DI, которая соответствует вашим требованиям.

Ответ 2

Здесь объясняется:

  • Transient - новый экземпляр создается каждый раз
  • Scoped - один экземпляр создается внутри текущей области. Это эквивалентно Singleton в текущей области
  • Singleton - Создается один экземпляр и он действует как singleton
  • Экземпляр - задается конкретный экземпляр. Вы несете ответственность за свое первоначальное создание.

Альфа-версия имела следующие ограничения:

  • Он поддерживает только впрыск конструктора
  • Он может разрешать типы только с одним и только одним открытым конструктором
  • Он не поддерживает расширенные функции (например, для области потока или автоматического обнаружения).

Если вы не пишете действительно сложный продукт, то для вас должно быть достаточно контейнера DI. В других случаях вы можете попробовать библиотеки, которые вы уже упоминали, которые имеют расширенные функции.

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

Ответ 3

В чем разница между этими регистрациями?

  • Transient - создается каждый раз, когда он извлекается
  • Scoped - создается один раз для каждого HTTP-запроса и будет доступен для жизни http-запроса
  • Singleton - созданный экземпляр один раз и будет доступен для всего срока службы вашего приложения.
  • Экземпляр - эквивалент singleton, за исключением того, что вы предоставляете экземпляр объекта вместо фреймворка, создающего экземпляр

Источник: http://www.khalidabuhakmeh.com/asp-vnext-dependency-injection-lifecycles, http://dotnetliberty.com/index.php/2015/10/15/asp-net-5-mvc6-dependency-injection-in-6-steps/

Ответ 4

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

Сервисы ASP.NET могут быть настроены со следующими сроками жизни:

Transient

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

Scoped

Настраиваемые службы времени жизни создаются один раз для каждого запроса.

Singleton

Службы жизненного цикла Singleton создаются в первый раз, когда они запрашивается, а затем каждый последующий запрос будет использовать один и тот же пример. Если ваше приложение требует однотонового поведения, рекомендуется использовать контейнер услуг для управления сроком службы вместо реализации шаблона проектирования singleton и управления вашим жизни объектов в классе.

Экземпляр [только до RTM!]

Вы можете добавить экземпляр непосредственно в контейнер сервисов. Если вы это сделаете, этот экземпляр будет использоваться для всех последующих запросов (этот метод создаст экземпляр Singleton). Один ключ разница между службами экземпляра и услугами Singleton заключается в том, что Служба экземпляра создается в ConfigureServices, а Служба Singleton загружается с первого раза при первом запросе.


Обновлено в RTM

Обратите внимание, что в Asp.Net Core RTM docs Экземпляр удален. Экземпляры в основном такие же, как Синглтон, но у них была другая семантика инициализации (Singleton был ленивый загружен). Но теперь нет API AddInstance, только AddSignleton, который может принимать уже созданный экземпляр.