昨天讀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集合的一個實現。普普統統的兩個類