Поделиться через


Внедрение зависимостей в контроллеры в ASP.NET Core

Автор: Рик Андерсон (Rick Anderson)

ASP.NET Core контроллеры MVC явно запрашивают зависимости через конструкторы. ASP.NET Core имеет встроенную поддержку внедрения зависимостей (DI). DI упрощает тестирование и поддержку приложений.

Просмотр или скачивание примера кода (как скачать)

Внедрение конструктора

Службы добавляются в качестве параметра конструктора, и среда выполнения разрешает службу из контейнера служб. Службы обычно задаются с помощью интерфейсов. Например, рассмотрим приложение, которому требуется текущее время. Следующие интерфейсы предоставляют службу :

public interface IDateTime
{
    DateTime Now { get; }
}

В следующем коде реализуется интерфейс :

public class SystemDateTime : IDateTime
{
    public DateTime Now
    {
        get { return DateTime.Now; }
    }
}

Добавьте службу в контейнер сервисов:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IDateTime, SystemDateTime>();

    services.AddControllersWithViews();
}

Для получения дополнительной информации о теме, см. в разделе Время существования службы внедрения зависимости.

Следующий код отображает приветствие пользователю в зависимости от времени дня:

public class HomeController : Controller
{
    private readonly IDateTime _dateTime;

    public HomeController(IDateTime dateTime)
    {
        _dateTime = dateTime;
    }

    public IActionResult Index()
    {
        var serverTime = _dateTime.Now;
        if (serverTime.Hour < 12)
        {
            ViewData["Message"] = "It's morning here - Good Morning!";
        }
        else if (serverTime.Hour < 17)
        {
            ViewData["Message"] = "It's afternoon here - Good Afternoon!";
        }
        else
        {
            ViewData["Message"] = "It's evening here - Good Evening!";
        }
        return View();
    }

Запустите приложение, и в зависимости от времени отобразится сообщение.

Внедрение действий с помощью

позволяет внедрять службу непосредственно в метод действия без использования внедрения через конструктор:

public IActionResult About([FromServices] IDateTime dateTime)
{
    return Content( $"Current server time: {dateTime.Now}");
}

Внедрение действий с помощью

В следующем коде показано, как получить доступ к ключу служб из контейнера DI с помощью атрибута :

using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddKeyedSingleton<ICache, BigCache>("big");
builder.Services.AddKeyedSingleton<ICache, SmallCache>("small");
builder.Services.AddControllers();

var app = builder.Build();

app.MapControllers();

app.Run();

public interface ICache
{
    object Get(string key);
}
public class BigCache : ICache
{
    public object Get(string key) => $"Resolving {key} from big cache.";
}

public class SmallCache : ICache
{
    public object Get(string key) => $"Resolving {key} from small cache.";
}

[ApiController]
[Route("/cache")]
public class CustomServicesApiController : Controller
{
    [HttpGet("big")]
    public ActionResult<object> GetBigCache([FromKeyedServices("big")] ICache cache)
    {
        return cache.Get("data-mvc");
    }

    [HttpGet("small")]
    public ActionResult<object> GetSmallCache([FromKeyedServices("small")] ICache cache)
    {
        return cache.Get("data-mvc");
    }
}

Доступ к параметрам из контроллера

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

Создайте класс, представляющий параметры. Рассмотрим пример.

public class SampleWebSettings
{
    public string Title { get; set; }
    public int Updates { get; set; }
}

Добавьте класс конфигурации в коллекцию служб:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IDateTime, SystemDateTime>();
    services.Configure<SampleWebSettings>(Configuration);

    services.AddControllersWithViews();
}

Настройте приложение для чтения параметров из файла формата JSON:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile("samplewebsettings.json",
                    optional: false,
                    reloadOnChange: true);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Следующий код запрашивает параметры из контейнера служб и использует их в методе :

public class SettingsController : Controller
{
    private readonly SampleWebSettings _settings;

    public SettingsController(IOptions<SampleWebSettings> settingsOptions)
    {
        _settings = settingsOptions.Value;
    }

    public IActionResult Index()
    {
        ViewData["Title"] = _settings.Title;
        ViewData["Updates"] = _settings.Updates;
        return View();
    }
}

Контроллеры как службы

По умолчанию ASP.NET Core не регистрирует контроллеры в качестве служб в контейнере DI. Среда выполнения использует DefaultControllerActivator для создания экземпляров контроллера и разрешения служб из контейнера DI для параметров конструктора, но сам контроллер не разрешается из контейнера.

Вызов регистрирует все контроллеры в качестве служб в контейнере DI:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews().AddControllersAsServices();

Регистрация контроллеров в качестве служб включает:

  • Перехват создания контроллера с помощью пользовательского компонента.
  • Использование любого управления временем жизни DI для контроллеров.
  • Внедрение служб в контроллеры с помощью любого зарегистрированного конструктора, так как контейнер DI выбирает конструктор.

Дополнительные ресурсы

  • См. раздел Test controller logic in ASP.NET Core чтобы узнать, как упростить тестирование кода путем явного запроса зависимостей в контроллерах.
  • Поддержка контейнера внедрения зависимостей к ключу службы
  • Замените контейнер внедрения зависимостей по умолчанию на стороннюю реализацию.

Авторы: Рик Андерсон (Rick Anderson) и Стив Смит (Steve Smith)

ASP.NET Core контроллеры MVC явно запрашивают зависимости через конструкторы. ASP.NET Core имеет встроенную поддержку внедрения зависимостей (DI). DI упрощает тестирование и поддержку приложений.

Просмотр или скачивание примера кода (как скачать)

Внедрение конструктора

Службы добавляются в качестве параметра конструктора, и среда выполнения разрешает службу из контейнера служб. Службы обычно задаются с помощью интерфейсов. Например, рассмотрим приложение, которому требуется текущее время. Следующие интерфейсы предоставляют службу :

public interface IDateTime
{
    DateTime Now { get; }
}

В следующем коде реализуется интерфейс :

public class SystemDateTime : IDateTime
{
    public DateTime Now
    {
        get { return DateTime.Now; }
    }
}

Добавьте службу в контейнер сервисов:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IDateTime, SystemDateTime>();

    services.AddControllersWithViews();
}

Для получения дополнительной информации о теме, см. в разделе Время существования службы внедрения зависимости.

Следующий код отображает приветствие пользователю в зависимости от времени дня:

public class HomeController : Controller
{
    private readonly IDateTime _dateTime;

    public HomeController(IDateTime dateTime)
    {
        _dateTime = dateTime;
    }

    public IActionResult Index()
    {
        var serverTime = _dateTime.Now;
        if (serverTime.Hour < 12)
        {
            ViewData["Message"] = "It's morning here - Good Morning!";
        }
        else if (serverTime.Hour < 17)
        {
            ViewData["Message"] = "It's afternoon here - Good Afternoon!";
        }
        else
        {
            ViewData["Message"] = "It's evening here - Good Evening!";
        }
        return View();
    }

Запустите приложение, и в зависимости от времени отобразится сообщение.

Внедрение действий с помощью

позволяет внедрять службу непосредственно в метод действия без использования внедрения через конструктор:

public IActionResult About([FromServices] IDateTime dateTime)
{
    return Content( $"Current server time: {dateTime.Now}");
}

Доступ к параметрам из контроллера

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

Создайте класс, представляющий параметры. Рассмотрим пример.

public class SampleWebSettings
{
    public string Title { get; set; }
    public int Updates { get; set; }
}

Добавьте класс конфигурации в коллекцию служб:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IDateTime, SystemDateTime>();
    services.Configure<SampleWebSettings>(Configuration);

    services.AddControllersWithViews();
}

Настройте приложение для чтения параметров из файла формата JSON:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
                config.AddJsonFile("samplewebsettings.json",
                    optional: false,
                    reloadOnChange: true);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Следующий код запрашивает параметры из контейнера служб и использует их в методе :

public class SettingsController : Controller
{
    private readonly SampleWebSettings _settings;

    public SettingsController(IOptions<SampleWebSettings> settingsOptions)
    {
        _settings = settingsOptions.Value;
    }

    public IActionResult Index()
    {
        ViewData["Title"] = _settings.Title;
        ViewData["Updates"] = _settings.Updates;
        return View();
    }
}

Контроллеры как службы

По умолчанию ASP.NET Core не регистрирует контроллеры в качестве служб в контейнере DI. Среда выполнения использует DefaultControllerActivator для создания экземпляров контроллера и разрешения служб из контейнера DI для параметров конструктора, но сам контроллер не разрешается из контейнера.

Вызов регистрирует все контроллеры в качестве служб в контейнере DI:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews().AddControllersAsServices();
}

Регистрация контроллеров в качестве служб включает:

  • Перехват создания контроллера с помощью пользовательского компонента.
  • Использование любого управления временем жизни DI для контроллеров.
  • Внедрение служб в контроллеры с помощью любого зарегистрированного конструктора, так как контейнер DI выбирает конструктор.

Дополнительные ресурсы

  • См. раздел Test controller logic in ASP.NET Core чтобы узнать, как упростить тестирование кода путем явного запроса зависимостей в контроллерах.

  • Замените контейнер внедрения зависимостей по умолчанию на стороннюю реализацию.

ASP.NET Core контроллеры MVC явно запрашивают зависимости через конструкторы. ASP.NET Core имеет встроенную поддержку внедрения зависимостей (DI). DI упрощает тестирование и поддержку приложений.

Просмотр или скачивание примера кода (как скачать)

Внедрение конструктора

Службы добавляются в качестве параметра конструктора, и среда выполнения разрешает службу из контейнера служб. Службы обычно задаются с помощью интерфейсов. Например, рассмотрим приложение, которому требуется текущее время. Следующие интерфейсы предоставляют службу :

public interface IDateTime
{
    DateTime Now { get; }
}

В следующем коде реализуется интерфейс :

public class SystemDateTime : IDateTime
{
    public DateTime Now
    {
        get { return DateTime.Now; }
    }
}

Добавьте службу в контейнер сервисов:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IDateTime, SystemDateTime>();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Для получения дополнительной информации о теме, см. в разделе Время существования службы внедрения зависимости.

Следующий код отображает приветствие пользователю в зависимости от времени дня:

public class HomeController : Controller
{
    private readonly IDateTime _dateTime;

    public HomeController(IDateTime dateTime)
    {
        _dateTime = dateTime;
    }

    public IActionResult Index()
    {
        var serverTime = _dateTime.Now;
        if (serverTime.Hour < 12)
        {
            ViewData["Message"] = "It's morning here - Good Morning!";
        }
        else if (serverTime.Hour < 17)
        {
            ViewData["Message"] = "It's afternoon here - Good Afternoon!";
        }
        else
        {
            ViewData["Message"] = "It's evening here - Good Evening!";
        }
        return View();
    }

Запустите приложение, и в зависимости от времени отобразится сообщение.

Внедрение действий с помощью

позволяет внедрять службу непосредственно в метод действия без использования внедрения через конструктор:

public IActionResult About([FromServices] IDateTime dateTime)
{
    ViewData["Message"] = $"Current server time: {dateTime.Now}";

    return View();
}

Доступ к параметрам из контроллера

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

Создайте класс, представляющий параметры. Рассмотрим пример.

public class SampleWebSettings
{
    public string Title { get; set; }
    public int Updates { get; set; }
}

Добавьте класс конфигурации в коллекцию служб:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IDateTime, SystemDateTime>();
    services.Configure<SampleWebSettings>(Configuration);
    
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Настройте приложение для чтения параметров из файла формата JSON:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.AddJsonFile("samplewebsettings.json", 
                                optional: false,        // File is not optional.
                                reloadOnChange: false);
        })
        .UseStartup<Startup>();
}

Следующий код запрашивает параметры из контейнера служб и использует их в методе :

public class SettingsController : Controller
{
    private readonly SampleWebSettings _settings;

    public SettingsController(IOptions<SampleWebSettings> settingsOptions)
    {
        _settings = settingsOptions.Value;
    }

    public IActionResult Index()
    {
        ViewData["Title"] = _settings.Title;
        ViewData["Updates"] = _settings.Updates;
        return View();
    }
}

Контроллеры как службы

По умолчанию ASP.NET Core не регистрирует контроллеры в качестве служб в контейнере DI. Среда выполнения использует DefaultControllerActivator для создания экземпляров контроллера и разрешения служб из контейнера DI для параметров конструктора, но сам контроллер не разрешается из контейнера.

Вызов регистрирует все контроллеры в качестве служб в контейнере DI:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().AddControllersAsServices();
}

Регистрация контроллеров в качестве служб включает:

  • Перехват создания контроллера с помощью пользовательского компонента.
  • Использование любого управления временем жизни DI для контроллеров.
  • Внедрение служб в контроллеры с помощью любого зарегистрированного конструктора, так как контейнер DI выбирает конструктор.

Дополнительные ресурсы

  • См. раздел Test controller logic in ASP.NET Core чтобы узнать, как упростить тестирование кода путем явного запроса зависимостей в контроллерах.

  • Замените контейнер внедрения зависимостей по умолчанию на стороннюю реализацию.