本文將會根據情況持續更新。 作為一個 `Framework`,`ASP.NET Core` 提供了諸多的擴展點。使用內置的組件和預設的配置通常就能夠滿足部分需求,當需要擴展的時就需要先去找出這些擴展點。除了基於實際應用對 `ASP.NET Core` 進行擴展,也會故意搞一些不切實際的偽需求,解決一... ...
一、概述
本文將會根據情況持續更新。
作為一個 Framework
,ASP.NET Core
提供了諸多的擴展點。使用內置的組件和預設的配置通常就能夠滿足部分需求,當需要擴展的時就需要先去找出這些擴展點。除了基於實際應用對 ASP.NET Core
進行擴展,也會故意搞一些不切實際的偽需求,解決一些不會存在的問題。這樣的目的何在呢?一是為了加深對 ASP.NET Core
的理解,二是難保這些偽需求不會變成真需求。
二、WebHost.CreateDefaultHostBuilder
WebHost.CreateDefaultHostBuilder
靜態方法用於創建 WebHostBuilder
對象,它有三個重載:
public static IWebHostBuilder CreateDefaultBuilder();
public static IWebHostBuilder CreateDefaultBuilder(string[] args);
public static IWebHostBuilder CreateDefaultBuilder<TStartup>(string[] args) where TStartup : class;
ASP.NET Core
項目模板使用的是第二個重載。第一個重載其實沒多大必要,將第二個重載的 args
參數設置成預設為 null
也可以。使用第三個重載,可以少一次對 UseStartup<T>
的直接調用。
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder<Startup>(args);
備註:
CreateDefaultBuilder
不能滿足需求時,可自行通過new
創建WebHostBuilder
。比如CreateDefaultBuilder
在創建WebHostBuidler
調用了後者的UseDefaultServiceProvider
擴展方法會導致使用預設的DefaultServiceProviderFactory
,從而導致使用預設DI
容器( ServiceProvider ),雖然之後可以替換成Autofac
之類的,但可以控制直接使用而不是替換。
三、IWebHostBuilder.UseStartup
IWebHostBuilder.UseStartup
擴展方法用於使用 Startup
,它有兩個重載:
public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType);
public static IWebHostBuilder UseStartup<TStartup>(this IWebHostBuilder hostBuilder) where TStartup : class;
ASP.NET Core
項目模板使用的是第二個重載,即泛型版本。泛型版本內部實際上調用的是非泛型版本。如果 Startup
不是定義在 ASP.NET Core Web
項目而是另一個程式集中,可先通過反射獲取 Startup
的類型,然後調用非泛型版本。當然,通過反射來調用泛型版本也是可以的,但想不出這樣做的理由。
備註:
Startup
會被註冊為單例,多次調用UseStartup
只有最後一個有效。
應用名稱預設是Startup
類所在程式集的名稱,如果將Startup
類放在另一個程式集中,需要留意這一點。
如果不使用 Startup
類,不註冊服務,只配置中間件的話,可以使用 IWebHostBuilder.Configure
擴展方法:
public static IWebHostBuilder Configure(this IWebHostBuilder hostBuilder, Action<IApplicationBuilder> configureApp);
備註:
Configure
看似是添加中間件的方法,其實不然。
四、使用第三方依賴註入
在 Startup
中替換依賴註入容器,以 Autofac
為例。第一種是實現 ConfigureContainer
方法:
// ConfigureContainer is where you can register things directly
// with Autofac. This runs after ConfigureServices so the things
// here will override registrations made in ConfigureServices.
// Don't build the container; that gets done for you. If you
// need a reference to the container, you need to use the
// "Without ConfigureContainer" mechanism shown later.
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterModule(new AutofacModule());
}
第二種是實現 ConfigureServices
方法:
// ConfigureServices is where you register dependencies. This gets
// called by the runtime before the Configure method, below.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// Add services to the collection.
services.AddMvc();
// Create the container builder.
var builder = new ContainerBuilder();
// Register dependencies, populate the services from
// the collection, and build the container.
//
// Note that Populate is basically a foreach to add things
// into Autofac that are in the collection. If you register
// things in Autofac BEFORE Populate then the stuff in the
// ServiceCollection can override those things; if you register
// AFTER Populate those registrations can override things
// in the ServiceCollection. Mix and match as needed.
builder.Populate(services);
builder.RegisterType<MyType>().As<IMyType>();
this.ApplicationContainer = builder.Build();
// Create the IServiceProvider based on the container.
return new AutofacServiceProvider(this.ApplicationContainer);
}
第三種方法是採用自定義 IServiceProviderFactory
的方式,比如 Abp
:
public static class AbpAutofacAbpApplicationCreationOptionsExtensions
{
public static void UseAutofac(this AbpApplicationCreationOptions options)
{
ContainerBuilder builder = new ContainerBuilder();
options.Services.AddObjectAccessor<ContainerBuilder>(builder);
options.Services.AddSingleton<IServiceProviderFactory<ContainerBuilder>>((IServiceProviderFactory<ContainerBuilder>) new AbpAutofacServiceProviderFactory(builder));
}
}
備註:對於第三種方法,不用陷入先有雞還是先有蛋的困境,
WebHostBuilder
的Build
方法會創建一個HostingServiceProvider
。
五、服務註冊點
包含名為 ConfigureServices
或類似的方法的介面和類:
類/介面 | 程式集 | 命名空間 | 備註 |
---|---|---|---|
IStartup | Microsoft.AspNetCore.Hosting.Abstractions | Microsoft.AspNetCore.Hosting | 介面。 實現類定義於應用。 配合 IWebHostBuilder.UseStartup 方法。 |
Startup | 自定義 | 自定義 | 定義於應用。不繼承任何介面或類,實現 Configure 和 ConfigureServices 等方法。 配合 IWebHostBuilder.UseStartup 方法。 |
IWebHostBuilder | Microsoft.AspNetCore.Hosting.Abstractions | Microsoft.AspNetCore.Hosting | 介面。 |
WebHostBuilder : IWebHostBuilder | Microsoft.AspNetCore.Hosting | Microsoft.AspNetCore.Hosting | ConfigureServices 不會進行實際的服務註冊操作,當調用 Build 方法時才註冊。 |
六、中間件註冊點
包含名為 Configure
或類似方法的介面和類:
類/介面 | 程式集 | 命名空間 | 備註 |
---|---|---|---|
IStartup | Microsoft.AspNetCore.Hosting.Abstractions | Microsoft.AspNetCore.Hosting | 介面。實現類定義於應用。 配合 IWebHostBuilder.UseStartup 方法。 |
IHostingStartup | Microsoft.AspNetCore.Hosting.Abstractions | Microsoft.AspNetCore.Hosting | 介面。 |
Startup | 自定義 | 自定義 | 定義於應用。不繼承任何介面或類,實現 Configure 和 ConfigureServices 等方法。 配合 IWebHostBuilder.UseStartup 方法。 |
IStartupFilter | Microsoft.AspNetCore.Hosting.Abstractions | Microsoft.AspNetCore.Hosting | 介面。實現類定義於應用。需註冊為服務。 |
參考資料
ASP.NET Core 中的應用啟動
在 ASP.NET Core 中使用 IHostingStartup 從外部程式集增強應用
Autofac 集成 ASP.NET Core
Abp 依賴註入
ASP.NET Core 的擴展點