TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #750 1.22K
День шестьсот шестнадцатый. #ЗаметкиНаПолях
Внедрение Зависимостей в
ASP.NET Core. Продолжение (3/4)
Начало
Продолжение

Регистрация нескольких сервисов
Если в методе ConfigureServices используется несколько регистраций для одного интерфейса, то последняя из них имеет приоритет.
services.AddTransient<IMessageSender, EmailSender>();
services.AddTransient<IMessageSender, SMSSender>();
Здесь в приложении будет использован SMSSender.

Чтобы избежать случайной «перезаписи» зарегистрированных сервисов, можно использовать соответствующий TryAdd… метод (например, TryAddTransient). Тогда реализация будет добавлена, только если она ещё не была зарегистрирована ранее.
Важно отметить, что без использования TryAdd… зарегистрированы будут оба сервиса, но лишь последняя реализация будет использована при обнаружении сервиса.

Иногда нужно явно перезаписать предыдущую регистрацию. Тогда используется метод Replace, принимающий дескриптор сервиса:
services.Replace(
new ServiceDescriptor(typeof(IMessageSender),
typeof(SMSSender), ServiceLifetime.Transient)
);
Чтобы удалить все регистрации сервисов для определённого интерфейса, используется метод RemoveAll:
services.RemoveAll<IMessageSender>();

Использовать эти методы придётся редко. Например, чтобы предоставить свою реализацию одного из сервисов сторонней библиотеки.

Зачем же контейнер DI регистрирует несколько реализаций? Это может пригодиться, когда вам нужно, например, зарегистрировать несколько отправителей сообщений, валидаторов данных или бизнес-правил, которые должны будут применены одно за другим. В этом случае в конструктор зависимого класса внедряется коллекция сервисов:
public class Notifier {
IEnumerable<IMessageSender> _senders;

public Notifier(
IEnumerable<IMessageSender> senders) {
_senders = senders;
}
public void SendMessage() {
foreach (var s in _senders) {
// обработка каждого отправителя
}
}
}

Таким образом, если мы хотим добавить, скажем, отправку через пуш-уведомления, нам нужно только добавить реализацию и зарегистрировать её в контейнере DI. Это одно из ограничений стандартного контейнера. Другие, более продвинутые, позволяют автоматически сканировать сборку и добавлять все реализации интерфейса.

При регистрации нескольких реализаций может быть нежелательно регистрировать одинаковые реализации, что обычными методами не проверяется. В нашем случае, если случайно зарегистрировать SMSSender дважды, сообщение по смс будет отправлено 2 раза. Тогда можно использовать метод TryAddEnumerable, принимающий коллекцию дескрипторов сервисов:
services.TryAddEnumerable(new[]
{
new ServiceDescriptor(typeof(IMessageSender),
typeof(EmailSender), ServiceLifetime.Transient),
new ServiceDescriptor(typeof(IMessageSender),
typeof(SMSSender), ServiceLifetime.Transient),
new ServiceDescriptor(typeof(IMessageSender),
typeof(SMSSender), ServiceLifetime.Transient)
});
В этом случае будет зарегистрирована только одна реализация SMSSender.

Окончание следует…

Источник:
https://app.pluralsight.com/library/courses/aspdotnet-core-dependency-injection/
More from @netdeveloperdiary
  1. Sep 29, 2026Фото 3 (с) Анатолий Кулаков
  2. Sep 29, 2026День 2799. Конференция DotNext 2026. Часть 1 25 и 26 сентября в Москве прошла очередная ко…
  3. Sep 28, 2026День 2798. #Оффтоп Утиная Типизация в C# с Помощью Перехватчиков. Часть 2 Некоторое время…
  4. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  5. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  6. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →