上一節介紹了.Net Core 如何前置準備有關 IOC的物件,可以供程式呼叫 Provider 的方法來 Resolve Service。這節會介紹呼叫後實際上如何Resolve Service。
當選擇的 Provider 為 ServiceProviderEngineScope ,即可呼叫 GetService 來進行Resolve。圖中S1步驟,為一開始的呼叫,接著會往引擎的部位去進行,即 ServiceProviderEngine,也是呼叫GetService的函式,如圖S2步驟,會去找RealizedService的集合。此集合存放註冊的服務對應Resolve的委派函示。如果還未Resolve過,則需呼叫CreateServiceAccessor進一步由CallSiteFactory.GetCallSite來取得對應的CallSite物件。CallSiteFactory.GetCallSite 會先到 CallSiteFactory._cacheCallSite集合中找是否已經有對應的CallSite物件,如果沒有的話需呼叫CallSiteFactory.CreateCallSite函式來新增。
當依照之前註冊好的service資訊建立CallSite物件後,如圖S3步驟,會作一次驗證,也就是模擬一次實際Resolve看看是否有錯誤,如果有錯誤則, throw exception to handle。
接下來執行 DynamicServiceProviderEngine.RealizeService函式,此會回傳一個委派事件讓S1步驟的GetService來叫用。
圖S5步驟即為執行RealizeService函式,其參數為ServiceProviderEngineScope本身。隨 CallSite.kind 的不同,呼叫CallSiteRuntimeResolver 中的路線也不同。
下圖以CallSite.kind為Constructor為例:
S5步驟呼會於CallSiteRuntimeResolver類別中叫用函式,其路徑為:
Resolve > VisitCallSite > VisitRootCache > VisitCache > VisitCallSiteMain > VisitConstructor
如果跑到 VisitConstructor,勢必要找此服務的ConstructorCallSite物件來執行Resolve,產生實體。
附帶一提,如果Constructor 的參數有其它的物件也需要DI,會於呼叫路徑的VisitCallSiteMain中再次遞迴呼叫VisitCallSite,直到所有的參數都完成Resolve。
下圖再以CallSite.kind為Factory為例:
CallSite.kind 為 Factory,代表當初註冊服務是以委派的函式進行,會希望實作出的服務以自行設計的委派函式產生實體。
S5步驟呼會於CallSiteRuntimeResolver類別中叫用函式,其路徑為:
Resolve > VisitCallSite > VisitRootCache > VisitCache > VisitCallSiteMain > VisitFactory
如果跑到 VisitFactory,勢必要找此服務的FactoryCallSite物件來執行Resolve,也就是用當初註冊到ServiceDescriptor中的委派函式來產生實體。
GetService要看是什麼Provider中的,如果是DynamicServiceProviderEngine 會走IOC。
例如StartUp class 不是走IOC,其建構子中的參數物件需要執行 GetService的Provider是HostServiceProvider。
GetService決定要跑什麼 case 是在 註冊的時候註冊到 ServiceDescriptor 就先收集好的,都在system.type中的資訊內,
最後在 GetService 中 取得 ServiceCallSite 時 經過這些資訊判斷,產生 對應種類的 callSite (ConstantCallSite、FactoryCallSite、ConstructorCallSite)
Type.GetTypeInfo() 可以看見相關資訊包含有沒有constructor、有哪些method、public或private與組件資訊等。
下一節會開始探討 MiddleWare 如何運作。