Можно ли в рамках одного контейнера зарегистрировать более одного варианта реализации одного интерфейса?
Ответ от нейросети
sobes.tech AI
Что хотят услышать интервьюеры:
Да, в контейнере можно зарегистрировать несколько реализаций одного интерфейса. Но при обычном запросе по интерфейсу контейнер должен понимать, какую именно реализацию отдавать. Обычно для этого используют разные типы регистрации, именование, фабрики или получение всех реализаций сразу.
Определение:
В DI-контейнере одна абстракция, например интерфейс, может быть связана с несколькими конкретными классами. Это удобно, когда одна и та же логика должна работать по-разному в разных сценариях.
При разрешении зависимости контейнер либо возвращает одну выбранную реализацию, либо коллекцию всех зарегистрированных реализаций этого интерфейса, в зависимости от того, как сделан запрос.
Пример использования:
Например, есть интерфейс уведомлений и две реализации: отправка по email и в SMS. Оба варианта можно зарегистрировать в контейнере, а потом либо выбрать нужный по условию, либо получить все реализации и обработать их последовательно.
public interface INotificationSender
{
void Send(string message);
}
public class EmailNotificationSender : INotificationSender
{
public void Send(string message) { /* отправка email */ }
}
public class SmsNotificationSender : INotificationSender
{
public void Send(string message) { /* отправка SMS */ }
}
Если контейнер поддерживает получение всех реализаций, можно сделать так:
public class NotificationService
{
private readonly IEnumerable<INotificationSender> _senders;
public NotificationService(IEnumerable<INotificationSender> senders)
{
_senders = senders;
}
public void NotifyAll(string message)
{
foreach (var sender in _senders)
sender.Send(message);
}
}
Пояснение кода:
Код показывает типичный подход: под один интерфейс зарегистрированы две реализации.
Когда в конструктор запрашивается IEnumerable<INotificationSender>, контейнер передает все найденные реализации этого интерфейса.
Далее сервис итерируется по коллекции и вызывает одинаковый контракт Send у каждой реализации.
Если нужен не список, а одна конкретная реализация, обычно добавляют дополнительный механизм выбора: фабрику, ключ, условную регистрацию или отдельный интерфейс.
Ключевые моменты:
- Да, несколько реализаций одного интерфейса в одном контейнере регистрировать можно.
- При запросе одиночного
INotificationSenderконтейнер должен выбрать одну реализацию, и поведение зависит от конкретного DI-контейнера. - Для работы со всеми реализациями обычно запрашивают
IEnumerable<T>. - Если нужно выбирать конкретную реализацию, используют фабрики, ключи, метки или отдельные интерфейсы.
- Такой подход полезен, когда одна абстракция имеет несколько вариантов поведения для разных сценариев.