這篇文章簡單記錄 ASP.NET Core中 ,startup類的一些使用。api
在 Startup類中,通常有兩個方法:mvc
它們都在應用啓動時,被ASP.NET Core runtime 調用:app
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) { ... } }
當應用的 host 被built(創建)時,Startup類被指定到應用中。async
而在 Program 中,當 host builder 上的 Build 被調用時,應用的 host 被 built 。ide
而Startup類是經過調用WebHostBuilderExtensions.UseStartup<TStartup>方法指定的。ui
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); //Build方法被調用時,應用的host被創建,同時Startup被指定到應用中 } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>(); }
在startup類中,一種依賴注入的常見用法:this
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 , 當定義不一樣環境的Startup (例如,StartupDevelopment 等),在運行時,選擇合適的Startup。 spa
它有三個特色:code
1. 比較典型的是調用 Add{Service} 和 services.Configure{Service} 。例如:Configure Identity services.orm
2. host 可能會 在Startup方法被調用以前,配置一些服務。 例如: The host.
在startup被調用以前,CreateDefaultBuilder方法配置了一個host 。
3. Add{Service}是IServiceCollection的擴展方法,下面是一些使用:
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"))); services.AddDefaultIdentity<IdentityUser>() .AddDefaultUI(UIFramework.Bootstrap4) .AddEntityFrameworkStores<ApplicationDbContext>(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); // Add application services. 添加應用的服務 services.AddTransient<IEmailSender, AuthMessageSender>(); services.AddTransient<ISmsSender, AuthMessageSender>(); }
添加 services 到 service container 使它們在應用和Configure方法中可用。services方法能夠經過 dependency injection 或 ApplicationServices 解析。
Configure方法用來指定應用怎樣 處理HTTP request。請求管道(request pipeline)經過添加中間組件到IApplicationBuilder實例中來配置。
ASP.NET Core 模板 配置的管道:
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(); }
使用Use擴展方法添加一個或多箇中間組件到請求管道。例如,UseMvc擴展方法添加 Routing Middleware 到請求管道 而且配置MVC 做爲一個默認的處理器。
不使用Startup類配置services和request processing pipeline。在host builder 上調用ConfigureServices和Configure的簡便方法。若是存在多個ConfigureServices的調用,會依次添加。若是存在多個Configure方法的調用,最後一個Configure的調用會被使用。
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"]; ... }); }
使用 IStartupFilter ,在應用的Configure 中間件管道的開頭或末尾配置中間件。
IStartupFilter 實現Configure方法,它會接收和返回一個Action<IApplicationBuilder>。而IApplicationBuilder定義了一個類來配置一個應用的請求管道。
這些filters會按照添加到services container的順序被調用。
下面是一個例子:
RequestSetOptionsMiddleware
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"]; //取請求中的option參數 if (!string.IsNullOrWhiteSpace(option)) { _injectedOptions.Value.Option = WebUtility.HtmlEncode(option); } await _next(httpContext); } }
RequestSetOptionsMiddleware 中間件被配置在 RequestSetOptionsStartupFilter 類中:
public class RequestSetOptionsStartupFilter : IStartupFilter { public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next) { return builder => { builder.UseMiddleware<RequestSetOptionsMiddleware>(); next(builder); }; } }
IStartupFilter 在 ConfigureServices中被註冊到 service container, 而且從Startup類的外部加強Startup:
WebHost.CreateDefaultBuilder(args) .ConfigureServices(services => { services.AddTransient<IStartupFilter, RequestSetOptionsStartupFilter>(); }) .UseStartup<Startup>() .Build();
當option的查詢字符串存在時,中間件會在MVC中間件以前處理這個值
中間件的執行順序是按照IStartupFilter的註冊順序
這裏晚上補充下 ApplicationServices 解析services的使用
IApplicationBuilder app
app.ApplicationServices.GetService 方法
如上,IApplicationBuilder類型,便可獲得ApplicationServices,而後利用其方法來解析services
參考網址:
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/startup?view=aspnetcore-2.2