1. 程式人生 > >ASP.NET Core中的依賴注入(5):ServicePrvider實現揭祕【補充漏掉的細節】

ASP.NET Core中的依賴注入(5):ServicePrvider實現揭祕【補充漏掉的細節】

到目前為止,我們定義的ServiceProvider已經實現了基本的服務提供和回收功能,但是依然漏掉了一些必需的細節特性。這些特性包括如何針對IServiceProvider介面提供一個ServiceProvider物件,何建立ServiceScope,以及如何提供一個服務例項的集合。

一、提供一個ServiceProvider物件

我們知道當將服務型別指定為IServiceProvider介面並呼叫ServiceProvider的GetService方法是,ServiceProvider物件本身將會作為服務例項返回,這個特性可以利用一個自定義的Service來實現。如下面的程式碼片段所示,我們定義的這個ServiceProviderService既是一個Service,又是一個ServiceCallSite。它預設採用生命週期管理模式為Scoped,在Invoke和Build方法中,它直接將當前ServiceProvider作為提供的服務例項。在初始化ServiceTable的時候,我們額外新增一個針對ServiceProviderService的ServideEntry。

   1: internal class ServiceProviderService : IService, IServiceCallSite
   2: {
   3:     public ServiceLifetime Lifetime => ServiceLifetime.Scoped;
   4:     public IService Next { get; set; }
   5:  
   6:     public Expression Build(Expression provider)
   7:     {
   8:         return provider;
   9:
}
  10:  
  11:     public IServiceCallSite CreateCallSite(ServiceProvider provider, ISet<Type> callSiteChain)
  12:     {
  13:         return this;
  14:     }
  15:  
  16:     public object Invoke(ServiceProvider provider)
  17:     {
  18:         return provider;
  19:     }
  20: }
  21:  
  22: internal
class ServiceTable
  23: {
  24:     public ServiceTable(IServiceCollection services)
  25:     {
  26:         //解析ServiceCollection並新增相應ServiceEntry
  27:         this.ServieEntries[typeof(IServiceProvider)] = new ServiceEntry(new ServiceProviderService());
  28:     }
  29: }


二、建立ServiceScope

建立ServiceScope的目的在於建立作為當前ServiceProvider兒子的另一個ServiceProvider,新建立的ServiceProvider不僅與原來的ServiceProvider具有相同的根,同時共享所有的服務註冊資訊。利用這個新的ServiceProvider來代替現有的ServiceProvider,其主要的目的還是使我們能夠及時地回收提供的服務例項。ServiceScope是通過它的工廠ServiceScopeFactory來建立的,所以先建立瞭如下一個ServiceScopeFactory類和對應的ServiceScope,它們的定義與我們在前面一節介紹的完全一致。

   1: internal class ServiceScope : IServiceScope
   2: {
   3:     public IServiceProvider ServiceProvider { get; private set; }
   4:  
   5:     public ServiceScope(ServiceProvider serviceProvider)
   6:     {
   7:         this.ServiceProvider = serviceProvider;
   8:     }
   9:  
  10:     public void Dispose()
  11:     {
  12:         (this.ServiceProvider as IDisposable)?.Dispose();
  13:     }
  14: }
  15:  
  16: internal class ServiceScopeFactory : IServiceScopeFactory
  17: {
  18:     public ServiceProvider ServiceProvider { get; private set; }
  19:  
  20:     public ServiceScopeFactory(ServiceProvider serviceProvider)
  21:     {
  22:         this.ServiceProvider = serviceProvider;
  23:     }
  24:  
  25:     public IServiceScope CreateScope()
  26:     {
  27:         return new ServiceScope(this.ServiceProvider);
  28:     }
  29: }
  30:  
  31: internal class ServiceProvider : IServiceProvider, IDisposable
  32: {
  33:     
  34:     public ServiceProvider(ServiceProvider parent)
  35:     {
  36:         this.Root = parent.Root;
  37:         this.ServiceTable = parent.ServiceTable;
  38:     }
  39: }

為了讓ServiceProvider的GetService方法在服務型別指定為IServiceScopeFactory介面的時候能夠自動返回上面我們定義的ServiceScopeFactory物件,我們依然和上面一樣建立了一個自定義的Service,並將其命名為ServiceScopeFactoryService。與ServiceProviderService一樣,ServiceScopeFactoryService同時也是一個ServiceCallSite,在Build和Invoke方法中它會返回一個ServiceScopeFactory物件。為了讓這個它能夠生效,我們依然在ServiceTable初始化的時自動新增一個相應的ServiceEntry。

   1: internal class ServiceScopeFactoryService : IService, IServiceCallSite
   2: {
   3:     public ServiceLifetime Lifetime=> ServiceLifetime.Scoped;
   4:     public IService Next { get; set; }
   5:  
   6:     public IServiceCallSite CreateCallSite(ServiceProvider provider, ISet<Type> callSiteChain)
   7:     {
   8:         return this;
   9:     }
  10:  
  11:     public Expression Build(Expression provider)
  12:     {
  13:         return Expression.New(typeof(ServiceScopeFactory).GetConstructors().Single(), provider);
  14:     }
  15:  
  16:     public object Invoke(ServiceProvider provider)
  17:     {
  18:         return new ServiceScopeFactory(provider);
  19:     }
  20: }
  21:  
  22: internal class ServiceTable
  23: {
  24:     public ServiceTable(IServiceCollection services)
  25:     {
  26:         //解析ServiceCollection並新增相應ServiceEntry
  27:         this.ServieEntries[typeof(IServiceProvider)] =  new ServiceEntry(new ServiceProviderService());
  28:         this.ServieEntries[typeof(IServiceScopeFactory)] = new ServiceEntry(new ServiceScopeFactoryService());
  29:     }
  30: }


三、提供一組服務的集合

到目前為止,我們自定義的ServiceProvider尚不具備原生ServiceProvider的一項特性,那就是當呼叫GetService方法時將服務型別指定為IEnumerable<T>或者直接呼叫擴充套件方法GetServices時,得到的是一個服務例項的集合。這個特性可以通過一個自定義的ServiceCallSite來完成,我們將其命名為EnumerableCallSite。

   1: internal class EnumerableCallSite : IServiceCallSite
   2: {
   3:     public Type ElementType { get; private set; }
   4:     public IServiceCallSite[] ServiceCallSites { get; private set; }
   5:  
   6:     public EnumerableCallSite(Type elementType, IServiceCallSite[] serviceCallSites)
   7:     {
   8:         this.ElementType = elementType;
   9:         this.ServiceCallSites = serviceCallSites;
  10:     }
  11:  
  12:     public Expression Build(Expression provider)
  13:     {
  14:         return Expression.NewArrayInit(this.ElementType, this.ServiceCallSites.Select(
  15:             it => Expression.Convert(it.Build(provider), this.ElementType)));
  16:     }
  17:  
  18:     public object Invoke(ServiceProvider provider)
            
           

相關推薦

ASP.NET Core依賴注入5ServicePrvider實現揭祕補充漏掉細節

到目前為止,我們定義的ServiceProvider已經實現了基本的服務提供和回收功能,但是依然漏掉了一些必需的細節特性。這些特性包括如何針對IServiceProvider介面提供一個ServiceProvider物件,何建立ServiceScope,以及如何提供一個服務例項的集合。 一、提供一個Serv

ASP.NET CORE 使用 SESSION 轉載

Session 是儲存使用者和 Web 應用的會話狀態的一種方法,ASP.NET Core 提供了一個用於管理會話狀態的中介軟體。在本文中我將會簡單介紹一下 ASP.NET Core 中的 Session 的使用方法。     安裝配置 Session nuget 新增引用 M

Asp.net Core IdentityServer4 入門教程概念解析

什麽 ica 統一 理解 給他 分享 目錄 .net 系統 目錄 1、IdentityServer4 是什麽 2、什麽是OpenID和OAuth 2.0協議 3、IdentityServer4 可以用來做什麽 其他 1、IdentityServer4 是什麽 Ident

ASP.NET Core依賴注入5: ServiceProvider實現揭祕 總體設計

本系列前面的文章我們主要以程式設計的角度對ASP.NET Core的依賴注入系統進行了詳細的介紹,如果讀者朋友們對這些內容具有深刻的理解,我相信你們已經可以正確是使用這些與依賴注入相關的API了。如果你還對這個依賴注入系統底層的實現原理具有好奇心,可以繼續閱讀這一節的內容。 目錄一、ServiceCall

ASP.NET Core依賴注入5: ServiceProvider實現揭祕 解讀ServiceCallSite

通過上一篇的介紹我們應該對實現在ServiceProvider的總體設計有了一個大致的瞭解,但是我們刻意迴避一個重要的話題,即服務例項最終究竟是採用何種方式提供出來的。ServiceProvider最終採用何種方式提供我們所需的服務例項取決於最終選擇了怎樣的ServiceCallSite,而服務註冊是採用的S

ASP.NET Core依賴注入2依賴注入DI

IoC主要體現了這樣一種設計思想:通過將一組通用流程的控制從應用轉移到框架之中以實現對流程的複用,同時採用“好萊塢原則”是應用程式以被動的方式實現對流程的定製。我們可以採用若干設計模式以不同的方式實現IoC,比如我們在上面介紹的模板方法、工廠方法和抽象工廠,接下來我們介紹一種更為有價值的IoC模式,即依賴注入

ASP.NET Core依賴注入1控制反轉IoC

ASP.NET Core在啟動以及後續針對每個請求的處理過程中的各個環節都需要相應的元件提供相應的服務,為了方便對這些元件進行定製,ASP.NET通過定義介面的方式對它們進行了“標準化”,我們將這些標準化的元件稱為服務,ASP.NET在內部專門維護了一個DI容器來提供所需的服務。要了解這個DI容器以及現實其中

asp.net -mvc框架復習5-ASP.NET MVC的視圖簡單使用

font height logs 認識 知識 分類 ges mil c中 1.視圖分類 ASPX視圖(現在講解) Razor視圖(後面講解) ASPX 視圖: 2.@page指令 作用:頁面的聲明 要求:必須放在第一行,常用指令屬性如下: 3.服務器端內嵌

ASP.NET Core 2 學習筆記依賴註入

pub framework 三次 DDM order 包裝 差異 限制 cto 原文:ASP.NET Core 2 學習筆記(四)依賴註入ASP.NET Core使用了大量的依賴註入(Dependency Injection, DI),把控制反轉(Inversion Of

asp.net core ioc 依賴注入

1.生命週期 內建的IOC有三種生命週期: Transient: Transient服務在每次被請求時都會被建立。這種生命週期比較適用於輕量級的無狀態服務。 Scoped: Scoped生命週期的服務是每次web請求被建立。 Singleton: Singleton生命能夠週期服務在第一被請求時建立,在後續

.Net Core依賴注入服務使用總結

一、依賴注入   引入依賴注入的目的是為了解耦和。說白了就是面向介面程式設計,通過呼叫介面的方法,而不直接例項化物件去呼叫。這樣做的好處就是如果添加了另一個種實現類,不需要修改之前程式碼,只需要修改注入的地方將實現類替換。上面的說的通過介面呼叫方法,實際上還是需要去例項化介面的實現類,只不過不需要我們手動n

.NET Core之單元測試使用記憶體資料庫處理單元測試的資料庫依賴

目錄 定義一個待測試API 測試用例 為減少篇幅,隱藏了SampleEntity和SqliteDbContext 定義一個待測試API 如下,我們定義了一個名為Sample的API,其中有一個外部依賴項Sqli

Asp.Net Core WebAPI入門整理簡單示例

序列 open exc tor pda template ssa net found 一、Core WebAPI中的序列化 使用的是Newtonsoft.Json,自定義全局配置處理: // This method gets called by the runtime.

Asp.Net Core WebAPI入門整理跨域處理

使用 所有 ble 允許 需要 public cors 項目 listitem 一、Core WebAPI中的跨域處理 1.在使用WebAPI項目的時候基本上都會用到跨域處理 2.Core WebAPI的項目中自帶了跨域Cors的處理,不需要單獨添加程序包 3.使用方

asp.net core入門教程系列

home padding 方式 title sys 活性 elf tro ash Asp.Net Core簡介 ASP.NET Core 是一個全新的開源、跨平臺框架,可以用它來構建基於網絡連接的現代雲應用程序,比如:Web 應用,IoT(Internet Of Thin

asp.net core 擁抱 docker 技術 概覽

測試 docker 架構 swa ima 進程 基於 概念 registry 這是一個huge 坑慢慢填吧。這裏只是一個目錄 或總覽。 docker 是什麽? docker可以看做一種虛擬機技術,但沒有傳統虛擬機那麽復雜,是基於進程的虛擬,就是讓一個一個進程,認為自己處於一

ASP.NET Core 2 學習筆記視圖

部分 合成 cati 分享 col script text var AC ASP.NET Core MVC中的Views是負責網頁顯示,將數據一並渲染至UI包含HTML、CSS等。並能痛過Razor語法在*.cshtml中寫渲染畫面的程序邏輯。本篇將介紹ASP.NET Co

ASP.NET Core 2 學習筆記生命周期

RF Go 使用 HR runt block top 最大的 env 原文:ASP.NET Core 2 學習筆記(二)生命周期要了解程序的運行原理,就要先知道程序的進入點及生命周期。以往ASP.NET MVC的啟動方式,是繼承 HttpApplication 作為網站開始

ASP.NET Core 2 學習筆記路由

local quest urn AD term 執行 自動 routes code 原文:ASP.NET Core 2 學習筆記(七)路由ASP.NET Core通過路由(Routing)設定,將定義的URL規則找到相對應行為;當使用者Request的URL滿足特定規則條件

ASP.NET Core 2 學習筆記MVC

方便 web redirect AR return his 架構模式 PE ofo 原文:ASP.NET Core 2 學習筆記(六)MVC ASP.NET Core MVC跟ASP.NET MVC觀念是一致的,使用上也沒有什麽太大的變化。之前的ASP.NET MVC把MV