我心中的ASP.NET Core 新核心對象WebHost(一)

以本系列文章向Fish 前輩的那篇 我心中的ASP.NET 核心對象 致敬。(雖然不知道前輩如今在幹什麼)。一晃就6年過去了,那首  郝雲 的《回到那一天》怎麼唱來着? 時光一晃,你就三十了。
而咱們都變成了老了的程序員 🙂
 
ASP.NET Core在解開了對windows的依懶以後,整個管線都發生了變化 。這個變化是完全的,原來ASP.NET 中的有些對象直接沒有了。被保留下來的,也只是你看起來還差很少,但實現已經徹底不同了。
 
咱們就來講說我認爲的這些ASP.NET Core的這些新的核心對象。
WebHost,  IServiceCollection,IServiceProvider,IApplicationBuilder,IMiddleware 和 RequestDelegate, IServer和IHttpApplication
還有一些一樣很重要的對象: ILogger, IConfiguration 

始於WebHost

WebHost像母親,它承載和孕育了ASP.NET Core下幾乎全部的對象,從代碼層面入手來看的話能夠說是ASP.NET Core的入口,沒有它,後面的一切都沒有辦法開始。固然如何複雜的一項業務,要作好也不容易,WebHost的啓動一共分爲四階段。
  • 準備階段: var builder = new WebHostBuilder(),而後給WebHostBuilder各類填參數
  • 構建階段: var host = builder.Builder() , 主要負責依懶注入的初始化,以及host的初始化
  • 啓動階段: host.start(); 
  • 運行階段

program.cs

ASP.NET Core 程序基於一個命令行的程序運行,程序的入口在program.cs的main方法。javascript

public static void Main(string[] args) {
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .Build()
        .Run();
}
WebHost是一個internal類,我相信NETCore團隊不但願你們隨意的去new它,而是經過WebHostBuilder去構建。咱們在這裏訪問的WebHost實際上不是真正的WebHost,真正的WebHost在github的Hosting項目下,命名空間爲:Microsoft.AspNetCore.Hosting.Internal。
在ASP.NET Core1x中,咱們必需要本身建立WebHostBuilder。
var host = new WebHostBuilder()
                .UseKestrel()
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup<Startup>()
                .Build();
這些默認的動做未免有些繁瑣,後來到了ASP.NET Core2的時候建立了一個新的項目在github上,叫作MetaPackages 並在  Microsoft.AspNetCore的命名空間下建立了一個static class也就是咱們如今用到的這個,裏面主要的方法就是CreateDefaultBuilder。

CreateDefaultBuilder方法

這個方法負責返回給咱們一個WebHostBuilder, 而且調用瞭如下擴展方法:php

  • UseKestrel 使用kestrel server來處理請求
  • UseContentRoot 設置站點目錄 
  • ConfigureAppConfiguration
  • ConfigureLogging
其實和咱們在1X的時候本身構建是一個道理,而這些都是基於WebHostBuilder 的擴展方法它們來自於其它幾個不一樣的組件。

UseKestrel

WebHost負責託管ASP.NET Core,可是它並不真正從服務器網卡上監聽端口以及將網絡字節轉換到.net core的管道。這些由IServer來處理。css

這裏先簡單瞭解一下這個過程,咱們後面會在IServer的環節再詳述。咱們這裏使用的UseKestrel 來自於github上的項目 KestrelHttpServer。html

裏面的Kestrel項目下有一個WebHostBuilderKestrelExtensions類。裏面就是這個 UseKestrel擴展方法的定義:java

public static IWebHostBuilder UseKestrel( this IWebHostBuilder hostBuilder) {
    return hostBuilder.ConfigureServices(services =>
    {
    // Don't override an already-configured transport
    services.TryAddSingleton<
        ITransportFactory, 
        SocketTransportFactory>();

    services.AddTransient<
        IConfigureOptions<KestrelServerOptions>, 
        KestrelServerOptionsSetup>();

    services.AddSingleton<
        IServer, 
        KestrelServer>();
    });
}

其實也很簡單,都是在進行Server依賴的配置,由於最終的執行都由WebHost來展控。因此WebHost大量依賴的其它外部組件都被定義成接口放到了HttpAbstractions裏面,而後由外部擴展方法(多以Use開頭,進行配置)git

ASP.NET Core源碼裏面大量使用擴展方法進行Servier DI的配置,擴展方法定義在各類不一樣的命名空間以及項目下。若是不習慣或者不瞭解相關的部分會以爲有些痛苦。程序員

ConfigureAppConfiguration

這個方法專門用來爲 WebHostBuilder添加配置,包括appsettings.json的、命令行參數以及環境變量。關於配置這一節咱們留在後面具體來說。github

config.AddJsonFile(
        "appsettings.json", 
        optional: true, 
        reloadOnChange: true)
.AddJsonFile(
    $"appsettings.{env.EnvironmentName}.json", 
     optional: true, 
     reloadOnChange: true);

config.AddEnvironmentVariables();
config.AddCommandLine(args);

ConfigureLogging

logging也是 ASP.NET Core內置組件中的很重要一個,這個方法在默認已經爲咱們添加了appsettings中的logging配置以及控制檯log。關於日誌這一節咱們留在後面具體來說。web

logging.AddConfiguration(
        hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();

UseStartup<>

Startup.cs這個類主要作兩件事情的配置Service DI和http管道,這些都是在WebHost啓動以前就須要肯定下來的。而UseStartup就是將咱們定義的Startup.cs和 IStartup綁定起來,讓WebHost能夠找獲得。 怎麼綁定呢? 固然仍是依賴注入:json

if (typeof(IStartup)
     .GetTypeInfo()
     .IsAssignableFrom(startupType.GetTypeInfo()))
{
    services.AddSingleton(typeof(IStartup), startupType);
}
else
{
    services.AddSingleton(typeof(IStartup), sp =>
    {
    var hostingEnvironment = 
    sp.GetRequiredService<IHostingEnvironment>();

    return new ConventionBasedStartup(
    StartupLoader.LoadMethods(
         sp, 
         startupType, 
         hostingEnvironment.EnvironmentName));
    });
}

VS爲咱們添加的Startup.cs默認不繼續IStartup接口,因此是採用Convention的這種方式,固然咱們也能夠繼承IStartup則直接註冊成單例到應用程序。

以上是整個 WebHostBuilder的準備階段,即往裏面放了不少的參數。下一篇咱們將接着講Builder階段,給了你那麼多,你要開始製造點什麼東西給我了。

本文首發於公衆號jessetalk,轉載請保留公衆號二維碼。

分類: 技術隨筆

6 條評論

zhang · 2017年11月25日 下午1:06

支持

fei · 2017年11月25日 下午1:07

評論加郵箱是否有些多餘

碼農阿宇 · 2017年12月14日 下午10:06

感謝騰飛寫了這麼好的文章,已經轉發並註明了來源而且保留了公衆號二維碼 謝謝

Chain · 2017年12月29日 上午9:19

已學習。

Allen · 2018年2月27日 下午2:37

感謝

Jay · 2018年7月16日 下午6:13

支持,感謝

發表評論

電子郵件地址不會被公開。 必填項已用*標註

相關文章
相關標籤/搜索