如今流行的系統通常都採用依賴注入的實現方式,利用DI容器來直接獲取所用到的類/接口的實例。.net core也同樣採用DI的方式,提供了DI容器的接口IServiceCollection,並提供了基於該接口的缺省實現ServiceCollection。 html
這樣咱們就能夠再也不像之前同樣,須要引入第三方的Untiy、Autofac、Castle等DI組件了。 數據庫
在.net core源碼的ServiceCollectionExtensions的實現中,有三個註冊的方法AddScoped、AddSingleton、AddTransient。這其中的三個選項(Singleton、Scoped和Transient)體現三種對服務對象生命週期的控制形式。 框架
這個具體提及來就太多了,仍是查閱相關材料吧Jide
有了DI容器,咱們在使用時,能夠簡單的在Startup.cs程序中編寫上註冊語句,下面以操做日誌的倉儲類爲例: 工具
1 public void ConfigureServices(IServiceCollection services) 2 { 3 services.AddScoped<IOperLogRepository, OperLogRepository>(); 4 }
第一個泛型類型表示將要從容器中請求的類型(一般是一個接口)。第二個泛型類型表示將由容器實例化而且用於完成這些請求的具體類型。post
咱們在操做日誌的邏輯服務類使用操做日誌的倉儲時,就這樣寫: ui
1 public partial class OperLogAppService : IOperLogAppService 2 { 3 private IOperLogRepository service; 4 5 public OperLogAppService(IOperLogRepository service) 6 { 7 this.service = service; 8 } 9 10 public void Write(OperLogDto operLogDto) 11 { 12 this.service.Insert(operLogDto.AsInfo()); 13 } 14 }
系統會在建立OperLogAppService的實例時,會自動建立IOperLogRepository在DI容器中註冊OperLogRepository類的實例。 this
然而這種方式在框架中是有些不方便的。咱們知道,框架要求的是可擴展,可配置,在新增系統功能模塊時,還須要手工修改程序,在Startup.cs的ConfiguraeService中增長註冊(就算把全部註冊移到一個獨立的方法中也是同樣),就如同第一個代碼寫的同樣,包括註冊倉儲類、註冊邏輯服務類等等。而後編譯,再發布運行。每增長、修改一個模塊,都須要整個系統編譯、發佈,對運行中的系統影響仍是挺大的。 url
咱們的作法是,功能模塊都有一個自注冊的類。這個自注冊的類會將功能模塊中全部的倉儲類、邏輯服務類等都註冊進DI容器中。Startup.cs會自動查找全部功能模塊中的自注冊類,而後將相關內容註冊進DI容器中。這樣就能夠作到,每增長一個模塊,只須要將該模塊的應用程序集Dll複製到系統的運行目錄就好了,其餘的系統幫你搞定。 spa
按照上述思路,首先是建一個自注冊的類。這個類都抽象出一個接口IServiceRegister
1 public interface IServiceRegister 2 { 3 /// <summary> 4 /// 註冊 5 /// </summary> 6 void Register(IServiceCollection services); 7 }
咱們以通用模塊爲例子,自注冊的類應該是這樣的。
1 public class CommonServiceRegister : IServiceRegister 2 { 3 public void Register(IServiceCollection services) 4 { 5 services.AddDbContext<CommonDbContext>(option => option.UseDb<CommonDbContext>(services.BuildServiceProvider()), ServiceLifetime.Scoped); 6 7 services.AddScoped<IParaReferRepository, ParaReferRepository>(); 8 services.AddScoped<IParaReferAppService, ParaReferAppService>(); 9 services.AddScoped<ISystemParameterRepository, SystemParameterRepository>(); 10 services.AddScoped<ISystemParameterAppService, SystemParameterAppService>(); 11 … 12 } 13 }
這個類中service.AppScoped註冊的是倉儲層和邏輯層接口對應的實現類,咱們這裏只是列出了系統參數和引用參數的註冊。對於第一句AddDbContext,請參見:4.4 異構、多數據庫的存取組件
爲了在Startup.cs中本身查找並調用這些註冊類,仍是比較簡單的,程序以下:調用ReflectionHelper的GetSubTypes方法,獲取全部繼承IServiceRegister的實現類,對於每一個實現類,建立實例並將模塊的倉儲和邏輯服務註冊到DI容器中。ReflectionHelper的GetSubTypes方法,請參見:4.1 反射工具
1 IEnumerable<Type> serviceList = ReflectionHelper.GetSubTypes<IServiceRegister>(); 2 foreach (Type type in serviceList) 3 { 4 IServiceRegister register = ReflectionHelper.CreateInstance(type) as IServiceRegister; 5 6 register.Register(services); 7 }
.net framework也能夠按照上述思路進行,不一樣的就是.net framework沒有startup.cs,只須要將上面的內容寫進global.asax便可,還有一點不一樣是IServiceCollection,可使用Unity等DI組件提供的DI容器。