ASP.NET Core 控制器的相依性插入Dependency injection into controllers in ASP.NET Core

作者:Shadi NamroutiRick AndersonSteve SmithBy Shadi Namrouti, Rick Anderson, and Steve Smith

ASP.NET Core MVC 控制器會透過建構函式明確地要求相依性。ASP.NET Core MVC controllers request dependencies explicitly via constructors. ASP.NET Core 內建相依性插入 (DI) 支援。ASP.NET Core has built-in support for dependency injection (DI). DI 可讓您更輕鬆地測試和維護應用程式。DI makes apps easier to test and maintain.

檢視或下載範例程式碼 (英文) (如何下載)View or download sample code (how to download)

建構函式插入Constructor Injection

服務會新增來作為建構函式參數,而執行階段會解析來自服務容器的服務。Services are added as a constructor parameter, and the runtime resolves the service from the service container. 通常可以使用介面來定義服務。Services are typically defined using interfaces. 例如,假設應用程式需要目前的時間。For example, consider an app that requires the current time. 下列介面會公開 IDateTime 服務:The following interface exposes the IDateTime service:

public interface IDateTime
{
    DateTime Now { get; }
}

下列程式碼會實作 IDateTime 介面:The following code implements the IDateTime interface:

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

將服務新增至服務容器:Add the service to the service container:

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

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

如需 AddSingleton 的詳細資訊,請參閱 DI 服務存留期For more information on AddSingleton, see DI service lifetimes.

下列程式碼會根據時段來向使用者顯示問候語:The following code displays a greeting to the user based on the time of day:

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();
    }

執行應用程式,並根據時間顯示訊息。Run the app and a message is displayed based on the time.

使用 FromServices 進行動作插入Action injection with FromServices

FromServicesAttribute 能夠將服務直接插入至動作方法,而不需使用建構函式插入:The FromServicesAttribute enables injecting a service directly into an action method without using constructor injection:

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

    return View();
}

從控制器存取設定Access settings from a controller

從控制器存取應用程式或組態設定是常見的模式。Accessing app or configuration settings from within a controller is a common pattern. ASP.NET Core 中的選項模式 中所述的「選項模式」是管理設定的慣用方法。The options pattern described in ASP.NET Core 中的選項模式 is the preferred approach to manage settings. 一般而言,不要將 IConfiguration 直接插入至控制器。Generally, don't directly inject IConfiguration into a controller.

建立要代表選項的類別。Create a class that represents the options. 例如:For example:

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

將設定類別新增至服務集合:Add the configuration class to the services collection:

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

設定應用程式以從 JSON 格式的檔案中讀取設定:Configure the app to read the settings from a JSON-formatted file:

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>();
}

下列程式碼會向服務容器要求 IOptions<SampleWebSettings> 設定,並在 Index 方法中使用它們:The following code requests the IOptions<SampleWebSettings> settings from the service container and uses them in the Index method:

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();
    }
}

其他資源Additional resources