Внедрение зависимостей (Dependency Injection) в C#
Внедрение зависимостей (Dependency Injection) в C#
Dependency Injection
Dependency Injection (DI) — это паттерн проектирования, который позволяет внедрять зависимости (сервисы) в классы извне, а не создавать их внутри. Это делает код гибким, тестируемым и поддерживаемым. В .NET DI встроен в ядро фреймворка.
Зависимость (Dependency) — это любой внешний сервис, который использует ваш класс:
- Базы данных (DbContext)
- HTTP-клиенты (HttpClient)
- Логгеры (ILogger)
- Репозитории, внешние API и т. д.
Внедрение зависимостей — это передача этих сервисов извне (через конструктор, свойства или методы), а не создание их внутри класса. Без DI, зависимости создаются внутри класса, образуя «жесткую связь». Это сложно тестировать, менять и это нарушает один из принципов проектирования SOLID - принцип единственной ответственности (SRP).
public class OrderService
{
private readonly ILogger _logger = new FileLogger(); // Жёсткая привязка
private readonly IPaymentGateway _gateway = new PayPalGateway(); // Трудно тестировать
public void ProcessOrder(Order order)
{
_logger.Log("Processing order...");
_gateway.ProcessPayment(order.Total);
}
}
Хорошим кодом считается внедрение зависимостей извне:
public class OrderService
{
private readonly ILogger _logger;
private readonly IPaymentGateway _gateway;
// Зависимости передаются через конструктор
public OrderService(ILogger logger, IPaymentGateway gateway)
{
_logger = logger;
_gateway = gateway;
}
public void ProcessOrder(Order order)
{
_logger.Log("Processing order...");
_gateway.ProcessPayment(order.Total);
}
}
Как они внедряются?
- Через конструктор (Constructor Injection). Это самый популярный способ, зависимости передаются при создании объекта:
public class UserService
{
private readonly IUserRepository _repo;
public UserService(IUserRepository repo)
{
_repo = repo;
}
}
- Через свойства (Property Injection). Реже используется, но подходит для опциональных зависимостей:
public class ReportGenerator
{
public ILogger Logger { get; set; } // Можно не задавать
}
- Через методы (Method Injection). Зависимость передаётся в конкретный метод:
public class DataExporter
{
public void Export(ISerializer serializer) { ... }
}
.NET предоставляет встроенный IoC-контейнер (IServiceProvider), который управляет зависимостями.
Так работает регистрация сервисов в Program.cs или Startup.cs.
var builder = WebApplication.CreateBuilder(args);
// 1. Singleton (один экземпляр на всё приложение)
builder.Services.AddSingleton<ILogger, FileLogger>();
// 2. Scoped (один экземпляр на запрос в веб-приложении)
builder.Services.AddScoped<IUserRepository, UserRepository>();
// 3. Transient (новый экземпляр при каждом запросе)
builder.Services.AddTransient<IEmailService, EmailService>();
var app = builder.Build();
- Singleton - один экземпляр на всё приложение. Подходит для кеша, конфигурации.
- Scoped - один экземпляр на область (например, HTTP-запрос).
- Transient - новый экземпляр при каждом обращении. Подходит для лёгких сервисов.
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). Исходный код хранится в файлах .cs для C. Там пишется логика приложения. В проекте можно создавать новые файлы, и через внутреннее API платформы будет взаимодействие между ними. Допустим, можно… Фундамент для начинающего программиста - что повторить, как работать, чего ожидать. Справочник-шпаргалка по конфигурациям в C — типы, синтаксис, стандартная библиотека, типовые паттерны. Не заменяет пошаговое обучение. Учебный курс — раздел. Набор советов, правил, принципов и обычаев в разработке на этом языке. Кавычки, точки, запятые, скобки и прочие знаки препинания. Ключевое слово Назначение Пример ------------------------------------ if Условное выполнение блока кода при истинности выражения if (count 0) Process(); else Альтернативное выполнение при ложности… Набор функций, которые включены в стандартную библиотеку языка. И если глобальные пространства имён применяются для общего и не используются для всего подряд, то в каждом файле добавляются свои, нужные для кода файла пространства - это file-scoped namespaces,… манипулировать данными (арифметические, логические, сравнительные операторы). Самый базовый способ ветвления — оператор if. Он проверяет условие и, если оно истинно (true), выполняет блок кода. Ошибка (error) — это, как правило, системный сбой, который невозможно обработать (например, нехватка памяти). Исключение (exception) — это управляемое отклонение, которое можно предвидеть,… Платформо-зависимые исключения — например, PlatformNotSupportedException используется в кроссплатформенных API, когда функция недоступна на текущей ОС.C# - язык программирования платформы .NET
Что требуется знать перед началом изучения языка программирования C#
Справочник по конфигурациям в C#
Рекомендации по разработке на C#
Синтаксис и пунктуация в C#
Ключевые слова языка C#
Встроенные функции и методы C#
Пространства имён в C#
Управляющие конструкции и логические операторы
Условные выражения и ветвления
Обработка исключений в C#
Иерархия классов исключений в C#