在 Host運作總覽最後階段,有展示出HostBuilder.Run()的階段,其中一個task為 Host.StartAsync(),會先執行產生ApplicationBuilder實體的任務,此時體會傳入GenericWebHostService.Options.ConfigureApplication,再利用 ConfigurationBuilder.Build去執行Startup中的Configure函式。
這個函式可以供開發者利用建構好的ApplicaitonBuilder去加入一些MiddleWare。
這節會展示和MVC的Controller相關的MiddleWare – UseEndpoint。
首先,會在Startup 類別中,於Configure函式執行:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
下圖展示一開始的進入點:
開始到S1步驟,會先到 VerifyRoutingServicesAreRegistered 函式驗證是否已經註冊好 RoutingMarkerService 到 service。接下來S2步驟,會到VerifyEndpointRoutingMiddlewareIsRegistered 函式驗證是否DefaultEndpointRouteBuilder實體已經準備好。驗證的方式脫離不了由本身IOC的機制。
然後接續執行 DefaultEndpointRouteBuilder.MapControllers 函式:
DefaultEndpointRouteBuilder.MapControllers 函式主要會呼叫GetOrCreateDataSource,其中會將 ControllerActionEndpointDataSource 此類別 Resolve 好,加入到 DefaultEndpointRouteBuilder.DataSources 中。Resolve的方式是由本身IOC的機制中的ServiceProvider 的 GetRequiredService 來進行。
接著 ControllerActionEndpointDataSource被實體出來後會有那些物件關聯:
比較重要的物件是,ControllerActionEndpointConventionBuilder 類別會被實體出來後,指派到 ControllerActionEndpointDataSource.DefaultBuilder。
再利用 DefaultActionDescriptorCollectionProvider 類別中的屬性_actionDescriptorProvider,執行 ControllerActionDescriptorProvider.OnProvidersExecuting,進而執行GetDescriptors函式。
ControllerActionDescriptorProvider有個屬性為_partManager,屬於ApplicationPartManager,在之前HostBuilder做 CreateProvider時,就已經被Resolve過,為Singleten,所以它的 FeatureProvider有存在一個ControllerFeatureProvider;另一個屬性為 ApplicationParts 亦為同時存在,並已存放專案的Assembly資訊。
而這邊會把組件內的Controller Type透過包裝到ControllerFeature類別中,送到_applicationModelFactory.CreateApplicationModel函式去處理。
CreateApplicationModel會依照四個_applicationModelFactory._applicationModelProviders分別為DefaultApplicationModelProvider、AuthorizationApplicationModelProvider、CorsApplicationModelProvider、ApiBehaviorApplicationModelProvider將Controller Type 的相關資訊整理到 controllerModel中,如Actions集合、Attributes集合、Filters集合、ControllerProperties集合等資訊。
之後將Controller Action 資訊以ActionDescriptor類別存到DefaultActionDescriptorCollectionProvider._collection中。最後將DefaultActionDescriptorCollectionProvider指派到ControllerActionEndpointDataSource._actions。
詳細的執行流程可以參考下一節的內容。