asp。net5的依賴注入

昨天讀asp.net5的doc,看到了configure的配置時,提到在controller中訪問配置就是經過依賴注入的。asp.net5的不少功能都經過依賴注入來實現了,能夠看一下startup.cs中,有多少給出的是接口吧!這個概念我也知道好久了,如何實現一直未搞清,並且在.net環境下,也有幾個成熟的方案,但由於不是.net框架的一部分,因此我從未上手使用過,對這一塊一直是模模糊糊。即然想用asp.net5做爲本身下一步的開發環境,仍是啃一會兒吧!git

就概念上說,依賴注入就是解決強耦合問題的。之前寫代碼用到 .net的框架以及第三方庫,都是提供好一個個的類,而後咱們就是實例化這個類,調用它的各個方法來寫程序。這樣有問題嗎?沒問題,我喜歡。 但有人卻不喜歡,非要「注入」一下。因而「接口」 、構造函數注入 、屬性注入就產生了。github

先看一下如何基於asp.net5的依賴注入寫代碼吧,其它框架的注入應該還有不一樣的,就無論它了。c#

首先在startup.cs中,mvc

        public void ConfigureServices(IServiceCollection services)
        {
            //根據asp.net的文檔,這樣添加一個單件對象。整個項目能夠用。
            services.AddSingleton(_ => Configuration);
        }

services 從哪兒來,是運行時傳入的,框架

Configureation從哪兒來,它是(new ConfigurationBuilder( ) ).build()出的一個對象。包含項目的配置信息,好比author,conntectstring等,這樣咱們從其它地方能夠訪問。asp.net

咱們轉到controller中,增長下面的代碼就算注入成功了。咱們隨時能夠用_config來訪問配置信息。ide

        private readonly IConfiguration _config;
        public HomeController(IConfiguration config)
        {
            _config = config;
        }

此時本應該去asp.net5的官方文檔查一下,但上面到目前爲止,依賴注入的章節標記爲未完成,就是說還沒人寫出來。函數

而後去github找到https://github.com/aspnet/DependencyInjection, 上面寫着這個包的用途是:ui

「Contains the common DI abstractions that ASP.NET 5 and EF 7 use, as well as adapters for some IoC containers」。spa

先下載下來源碼吧!複製項目地址,而後到vs2015中,克隆一下。

先回到asp.net5的項目模版中,看一下這兩個提示

的確,IServiceCollection的命名空間是依賴注入的名字,而AddSingleton的方法只是那個接口的一個擴展。

AddSingleton方法上點右鍵,查看元信息。一切信息都對。

至此解決我了一個大疑惑:我一直覺得IServiceCollection是asp.net5提供的許多服務呢,好比ef,mvc,route等服務。

若是想用MVC,則在服務中添加一下就行。誰他媽的能想到,這個service的意思是注入服務的。並且這個接口就是用來注入的。

這是克隆下來的源碼,包含3個項目,能夠在裏面找一下上面的這些接口以及類,均可以找到。

由此更加可知,IServiceCollection就是依賴注入的一個接口。


待我細細讀一下源碼,再繼續分析吧!

-------------------------------------------------------------------------------------

繼續分析,先把昨天下午看的部分寫一下,就是下面打紅勾部分,很簡單!

1~5都很簡單,就是普通的類及集合的封裝,全部的祕密可能都藏在6裏,我還沒弄懂!

第1: 只是一個接口,沒有任何其它內容。它指示了集合對象是:ServiceDescriptor

public interface IServiceCollection : IList<ServiceDescriptor>
    {
    }

第2:覺得很神祕的ServiceDescriptor,其實只一個普通的類。應該是待註冊的每個類的描述信息。

ServiceDescriptor主要是5個屬性,以及大量的靜態方法,這些方法也只是爲了構造一個類對象。

  public ServiceLifetime Lifetime { get; }
  public Type ServiceType { get; }
  public Type ImplementationType { get; }
  public object ImplementationInstance { get; }
  public Func<IServiceProvider, object> ImplementationFactory { get; }

Lifetime屬性是枚舉值,就是第3個文件內容:

public enum ServiceLifetime
    {
        Singleton,
        Scoped,
        Transient  //短暫的,暫時的
    }

另外4個屬性的目的就是提供兩個值,服務的類型以及實現類型。這4個屬性未必要構造時給值,就是說能夠爲空的,只要能判斷出來那2個類型便可。而且這兩個類型能夠相同的。

這個類有3個構造函數,以及Instance,Describe,Transient,Scoped,Singleton這5個靜態函數的擴展,使用大量重載。這5個靜態函數最終都是調用構造函數,並返回ServiceDescriptor的一個對象。

第5: 

  我感受應該先講第5,後講第4. 前面提到IServiceCollection只是一個接口,接口繼承了IList。那它怎麼實現? 它實現的類內部還要增長一個List對象.

裏面的方法都轉爲List方法的調用。

第4: 它是IServiceCollection靜態擴展:

Add  AddTransient  AddScoped  AddSingleton  AddInstance ------最終都是調用Add直接插入到服務集合中

 TryAdd  TryAddTransient  TryAddScoped  TryAddSingleton  TryAddEnumerable ------最終都是調用TryAdd直接插入到服務集合中

Replace   --去查找第1個ServiceType相同的元素,有就刪除,最後插入這個服務。


至此,只是ServiceDescriptor 類以及ServiceCollection集合的一個實現。普普統統的兩個類

相關文章
相關標籤/搜索