Startup 類

2019-04-17 08:58 更新

Startup 類

ASP.NET Core 應(yīng)用使用 Startup 類,按照約定命名為 Startup。 Startup 類:

  • 可選擇性地包括 ConfigureServices 方法以配置應(yīng)用的服務(wù)。 服務(wù)是一個(gè)提供應(yīng)用功能的可重用組件。 在 ConfigureServices 中配置配置(也稱為“注冊(cè)”)并通過依存關(guān)系注入 (DI) 或 ApplicationServices 在整個(gè)應(yīng)用中使用。
  • 包括 Configure 方法以創(chuàng)建應(yīng)用的請(qǐng)求處理管道。

當(dāng)應(yīng)用啟動(dòng)時(shí),運(yùn)行時(shí)調(diào)用 ConfigureServices 和 Configure:

C#

public class Startup
{
    // Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        ...
    }

    // Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app)
    {
        ...
    }
}

在構(gòu)建應(yīng)用的主機(jī)時(shí),系統(tǒng)為應(yīng)用指定 Startup 類。 在 Program 類的主機(jī)生成器上調(diào)用 Build時(shí),將生成應(yīng)用的主機(jī)。 通常通過在主機(jī)生成器上調(diào)用 WebHostBuilderExtensions.UseStartup<TStartup> 方法來指定 Startup 類:

C#

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

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

主機(jī)提供 Startup 類構(gòu)造函數(shù)可用的某些服務(wù)。 應(yīng)用通過 ConfigureServices 添加其他服務(wù)。 然后,主機(jī)和應(yīng)用服務(wù)都可以在 Configure 和整個(gè)應(yīng)用中使用。

在 Startup 類中注入依賴關(guān)系的常見用途為注入:

C#

public class Startup
{
    private readonly IHostingEnvironment _env;
    private readonly IConfiguration _config;
    private readonly ILoggerFactory _loggerFactory;

    public Startup(IHostingEnvironment env, IConfiguration config, 
        ILoggerFactory loggerFactory)
    {
        _env = env;
        _config = config;
        _loggerFactory = loggerFactory;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        var logger = _loggerFactory.CreateLogger<Startup>();

        if (_env.IsDevelopment())
        {
            // Development service configuration

            logger.LogInformation("Development environment");
        }
        else
        {
            // Non-development service configuration

            logger.LogInformation($"Environment: {_env.EnvironmentName}");
        }

        // Configuration is available during startup.
        // Examples:
        //   _config["key"]
        //   _config["subsection:suboption1"]
    }
}

注入 IHostingEnvironment 的替代方法是使用基于約定的方法。 應(yīng)用為不同的環(huán)境(例如,StartupDevelopment)單獨(dú)定義 Startup 類時(shí),相應(yīng)的 Startup 類會(huì)在運(yùn)行時(shí)被選中。 優(yōu)先考慮名稱后綴與當(dāng)前環(huán)境相匹配的類。 如果應(yīng)用在開發(fā)環(huán)境中運(yùn)行并包含 Startup 類和 StartupDevelopment 類,則使用 StartupDevelopment 類。 有關(guān)詳細(xì)信息,請(qǐng)參閱使用多個(gè)環(huán)境。

要詳細(xì)了解有關(guān)主機(jī)的詳細(xì)信息,請(qǐng)參閱主機(jī)。 有關(guān)在啟動(dòng)過程中處理錯(cuò)誤的信息,請(qǐng)參閱啟動(dòng)異常處理

ConfigureServices 方法

ConfigureServices 方法:

  • 可選。
  • 在 Configure 方法配置應(yīng)用服務(wù)之前,由主機(jī)調(diào)用。
  • 其中按常規(guī)設(shè)置配置選項(xiàng)。

典型模式是調(diào)用所有 Add{Service} 方法,然后調(diào)用所有 services.Configure{Service} 方法。 有關(guān)示例,請(qǐng)參閱配置標(biāo)識(shí)服務(wù)。

主機(jī)可能會(huì)在調(diào)用 Startup 方法之前配置某些服務(wù)。 有關(guān)詳細(xì)信息,請(qǐng)參閱主機(jī)。

對(duì)于需要大量設(shè)置的功能,IServiceCollection 上有 Add{Service} 擴(kuò)展方法。 典型 ASP.NET Core 應(yīng)用將為實(shí)體框架、標(biāo)識(shí)和 MVC 注冊(cè)服務(wù):

C#

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc();

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
}

將服務(wù)添加到服務(wù)容器,使其在應(yīng)用和 Configure 方法中可用。 服務(wù)通過依賴關(guān)系注入或 ApplicationServices 進(jìn)行解析。

Configure 方法

Configure 方法用于指定應(yīng)用響應(yīng) HTTP 請(qǐng)求的方式。 可通過將中間件組件添加到 IApplicationBuilder 實(shí)例來配置請(qǐng)求管道。 Configure 方法可使用 IApplicationBuilder,但未在服務(wù)容器中注冊(cè)。 托管創(chuàng)建 IApplicationBuilder 并將其直接傳遞到 Configure。

ASP.NET Core 模板配置的管道支持:

C#

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();

    app.UseMvc();
}

每個(gè) Use 擴(kuò)展方法將一個(gè)或多個(gè)中間件組件添加到請(qǐng)求管道。 例如,UseMvc 擴(kuò)展方法將路由中間件添加到請(qǐng)求管道,并將 MVC 配置為默認(rèn)處理程序。

請(qǐng)求管道中的每個(gè)中間件組件負(fù)責(zé)調(diào)用管道中的下一個(gè)組件,或在適當(dāng)情況下使鏈發(fā)生短路。 如果中間件鏈中未發(fā)生短路,則每個(gè)中間件都有第二次機(jī)會(huì)在將請(qǐng)求發(fā)送到客戶端前處理該請(qǐng)求。

其他服務(wù)(如 IHostingEnvironment 和 ILoggerFactory),也可以在 Configure 方法簽名中指定。如果指定,其他服務(wù)如果可用,將被注入。

有關(guān)如何使用 IApplicationBuilder 和中間件處理順序的詳細(xì)信息,請(qǐng)參閱 ASP.NET Core 中間件

便利方法

若要配置服務(wù)和請(qǐng)求處理管道,而不使用 Startup 類,請(qǐng)?jiān)谥鳈C(jī)生成器上調(diào)用 ConfigureServices和 Configure 便捷方法。 多次調(diào)用 ConfigureServices 將追加到另一個(gè)。 如果存在多個(gè) Configure 方法調(diào)用,則使用最后一個(gè) Configure 調(diào)用。

C#

public class Program
{
    public static IHostingEnvironment HostingEnvironment { get; set; }
    public static IConfiguration Configuration { get; set; }

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

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureAppConfiguration((hostingContext, config) =>
            {
            })
            .ConfigureServices(services =>
            {
                ...
            })
            .Configure(app =>
            {
                var loggerFactory = app.ApplicationServices
                    .GetRequiredService<ILoggerFactory>();
                var logger = loggerFactory.CreateLogger<Program>();
                var env = app.ApplicationServices.GetRequiredServices<IHostingEnvironment>();
                var config = app.ApplicationServices.GetRequiredServices<IConfiguration>();

                logger.LogInformation("Logged in Configure");

                if (env.IsDevelopment())
                {
                    ...
                }
                else
                {
                    ...
                }

                var configValue = config["subsection:suboption1"];

                ...
            });
}

使用 Startup 篩選器擴(kuò)展 Startup

在應(yīng)用的 Configure 中間件管道的開頭或末尾使用 IStartupFilter 來配置中間件。 IStartupFilter 有助于確保中間件在應(yīng)用請(qǐng)求處理管道的開始或結(jié)束時(shí)由庫添加的中間件之前或之后運(yùn)行。

IStartupFilter 實(shí)現(xiàn)單個(gè)方法(即 Configure),該方法接收并返回 Action<IApplicationBuilder>。IApplicationBuilder 定義用于配置應(yīng)用請(qǐng)求管道的類。 有關(guān)詳細(xì)信息,請(qǐng)參閱使用 IApplicationBuilder 創(chuàng)建中間件管道

在請(qǐng)求管道中,每個(gè) IStartupFilter 實(shí)現(xiàn)一個(gè)或多個(gè)中間件。 篩選器按照添加到服務(wù)容器的順序調(diào)用。 篩選器可在將控件傳遞給下一個(gè)篩選器之前或之后添加中間件,從而附加到應(yīng)用管道的開頭或末尾。

下面的示例演示如何使用 IStartupFilter 注冊(cè)中間件。

RequestSetOptionsMiddleware 中間件從查詢字符串參數(shù)中設(shè)置選項(xiàng)值:

C#

public class RequestSetOptionsMiddleware
{
    private readonly RequestDelegate _next;
    private IOptions<AppOptions> _injectedOptions;

    public RequestSetOptionsMiddleware(
        RequestDelegate next, IOptions<AppOptions> injectedOptions)
    {
        _next = next;
        _injectedOptions = injectedOptions;
    }

    public async Task Invoke(HttpContext httpContext)
    {
        Console.WriteLine("RequestSetOptionsMiddleware.Invoke");

        var option = httpContext.Request.Query["option"];

        if (!string.IsNullOrWhiteSpace(option))
        {
            _injectedOptions.Value.Option = WebUtility.HtmlEncode(option);
        }

        await _next(httpContext);
    }
}

在 RequestSetOptionsStartupFilter 類中配置 RequestSetOptionsMiddleware:

C#

public class RequestSetOptionsStartupFilter : IStartupFilter
{
    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    {
        return builder =>
        {
            builder.UseMiddleware<RequestSetOptionsMiddleware>();
            next(builder);
        };
    }
}

IStartupFilter 在 ConfigureServices 的服務(wù)容器中注冊(cè),參數(shù) Startup 從 Startup 類外部注冊(cè):

C#

WebHost.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddTransient<IStartupFilter, 
            RequestSetOptionsStartupFilter>();
    })
    .UseStartup<Startup>()
    .Build();

當(dāng)提供 option 的查詢字符串參數(shù)時(shí),中間件在 MVC 中間件呈現(xiàn)響應(yīng)之前處理分配值:

瀏覽器窗口顯示已呈現(xiàn)的索引頁。

中間件執(zhí)行順序由 IStartupFilter 注冊(cè)順序設(shè)置:

  • 多個(gè) IStartupFilter 實(shí)現(xiàn)可能與相同的對(duì)象進(jìn)行交互。 如果順序很重要,請(qǐng)將它們的 IStartupFilter 服務(wù)注冊(cè)進(jìn)行排序,以匹配其中間件應(yīng)有的運(yùn)行順序。
  • 庫可能添加包含一個(gè)或多個(gè) IStartupFilter 實(shí)現(xiàn)的中間件,這些實(shí)現(xiàn)在向 IStartupFilter注冊(cè)的其他應(yīng)用中間件之前或之后運(yùn)行。 若要在庫的 IStartupFilter 添加中間件之前調(diào)用 IStartupFilter 中間件,請(qǐng)?jiān)趯焯砑拥椒?wù)容器之前定位服務(wù)注冊(cè)。 若要在此后調(diào)用,請(qǐng)?jiān)谔砑訋熘蠖ㄎ环?wù)注冊(cè)。

在啟動(dòng)時(shí)從外部程序集添加配置

通過 IHostingStartup 實(shí)現(xiàn),可在啟動(dòng)時(shí)從應(yīng)用 Startup 類之外的外部程序集向應(yīng)用添加增強(qiáng)功能。有關(guān)更多信息,請(qǐng)參見在 ASP.NET Core 中使用承載啟動(dòng)程序集。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)