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

Что такое ИОК?

Инверсия управления (IoC) — это принцип проектирования, при котором поток приложения инвертируется по сравнению с традиционным процедурным программированием. Это означает, что вместо того, чтобы компонент контролировал свои зависимости, управление передается контейнеру или фреймворку. В контексте .NET контейнер IoC — это платформа для реализации автоматического внедрения зависимостей. Он управляет созданием объекта и его временем жизни, а также внедряет зависимости в класс.

Основным преимуществом использования контейнеров IoC в .NET является улучшенная ремонтопригодность и масштабируемость кода за счет уменьшения связи между компонентами и содействия повторному использованию кода.

Встроенный контейнер IoC в .NET 6

.NET 6 имеет встроенный контейнер IoC, который поддерживает внедрение конструктора, внедрение свойства и внедрение вызова метода.

Давайте рассмотрим пример того, как это можно использовать в приложении.

Предположим, у нас есть интерфейс IMessageService и класс EmailService, реализующий этот интерфейс:

public interface IMessageService
{
    void SendMessage(string message, string recipient);
}

public class EmailService : IMessageService
{
    public void SendMessage(string message, string recipient)
    {
        // logic to send email
    }
}

Мы можем внедрить эту службу в контроллер в приложении ASP.NET Core, используя встроенный контейнер IoC, сначала зарегистрировав службу в файле Startup.cs или Program.cs, а затем добавив в контроллер конструктор, который принимает IMessageService в качестве параметра:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IMessageService, EmailService>();
}
public class HomeController : Controller
{
    private IMessageService _messageService;

    public HomeController(IMessageService messageService)
    {
        _messageService = messageService;
    }

    public IActionResult Index()
    {
        _messageService.SendMessage("Hello World!", "[email protected]");
        return View();
    }
}

Понимание времени жизни в контейнерах IoC

Одним из важных аспектов, который следует учитывать при работе с контейнерами IoC в .NET, является управление временем существования объектов, созданных контейнером. Концепция времени жизни в контейнере IoC относится к тому, как долго экземпляр службы живет в памяти после его создания. .NET предоставляет три варианта времени жизни для регистрации службы: Singleton, Scoped и Transient.

Синглтон

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

services.AddSingleton<IMessageService, EmailService>();

Область применения

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

services.AddScoped<IMessageService, EmailService>();

Переходный

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

services.AddTransient<IMessageService, EmailService>();

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

Помните, что эффективное использование контейнеров IoC поможет вам писать приложения, которые легче тестировать, поддерживать и масштабировать.