歡迎光臨
每天分享高質量文章

輕量級.Net Core服務註冊工具CodeDi釋出啦

為什麼做這麼一個工具

因為我們的系統往往時面向介面程式設計的,所以在開發Asp .net core專案的時候,一定會有大量大介面及其對應的實現要在ConfigureService註冊到ServiceCollection中,傳統的做法是加了一個服務,我們就要註冊一次(service.AddService()),又比如,當一個介面有多個實現,在建構式中獲取服務也不是很友好,而據我所知, .Net Core目前是沒有什麼自帶的庫或者方法解決這些問題,當然,如果引入第三方容器如AutoFac這些問題時能迎刃而解的,但是如何在不引入第三方容器來解決這個問題呢?
所以我就設計了這樣的一個輕量級工具.

首先,放上該專案的Github地址(記得Star哦!!)

https://github.com/liuzhenyulive/CodeDi

CodeDi是一個基於 .Net Standard的工具庫,它能幫助我們自動地在Asp .net core或者 .net core專案中完成服務的註冊.

Overview

CodeDi 是 Code Dependency Injection的意思,在上次我在看了由依樂祝寫的<.net core=””/>後,回想起我之前遇到的那些問題,感覺撥雲見日,所以,我就開始著手寫這個工具了.

如何使用CodeDi

安裝Nuget包

CodeDi的Nuget包已經釋出到了 nuget.org,您可以透過以下指令在您的專案中安裝CodeDi

Install-Package CodeDi


ConfigureServices中的配置

方法 1

您可以在StartupConfigureService方法中新增AddCodeDi完成對CodeDi的呼叫.服務的註冊CodeDi會自動為您完成.

 


方法 2

您也可以在AddCodeDi方法中傳入一個Action引數,在這個action中,您可以對CodeDiOptions的屬性進行配置.

 


方法 3

當然您也可以直接給AddCodeDi()方法直接傳入一個CodeDiOptions實體.

 


你也可以在appsetting.json檔案中配置CodeDiOptions的資訊,並透過Configuration.Bind("CodeDiOptions", options)把配置資訊系結到一個CodeDiOptions實體.

appsetting.json file

 


ConfigureService方法

 


CodeDiOptions詳解

屬性名稱 屬性描述 資料型別 預設值
AssemblyPaths 在指定目錄下載入Dll程式集 string[] Bin目錄
AssemblyNames 選擇要載入的程式集名稱 (支援萬用字元) string[] *
IgnoreAssemblies 忽略的程式集名稱 (支援萬用字元) string[] null
IncludeSystemAssemblies 是否包含系統程式集(當為false時,會忽略含有System,Microsoft,CppCodeProvider,WebMatrix,SMDiagnostics,Newtonsoft關鍵詞和在App_Web,App_global目錄下的程式集) bool false
IgnoreInterface 忽略的介面 (支援萬用字元) string[] null
InterfaceMappings 介面對應的服務 (支援萬用字元) ,當一個介面有多個實現時,如果不進行配置,則多個實現都會註冊到SerciceCollection中 Dictionary null
DefaultServiceLifetime 預設的服務生命週期 ServuceLifetime( Singleton,Scoped,Transient) ServiceLifetime.Scope
ServiceLifeTimeMappings 指定某個介面的服務生命週期,不指定為預設的生命週期 Dictionary null

InterfaceMappings

如果 ISay 介面有SayInChinese 和SayInEnglish 兩個實現,我們只想把SayInEnglish註冊到ServiceCollection


那麼我們可以這樣配置InterfaceMappings.

options.InterfaceMappings=new Dictionary(){{ “ISay”, “SayInChinese” } }

也就是{介面名稱(支援萬用字元),實現名稱(支援萬用字元)}

ServiceLifeTimeMappings

如果我們希望ISay介面的服務的生命週期為Singleton,我們可以這樣配置ServiceLifeTimeMappings.

options.ServiceLifeTimeMappings = new Dictionary(){{“*Say”,ServiceLifetime.Singleton}};

也就是也就是{介面名稱(支援萬用字元),Servicelifetime}

關於ServiceLifetime: https://github.com/aspnet/DependencyInjection/blob/master/src/DI.Abstractions/ServiceLifetime.cs

獲取服務實體

當然, 您可以和之前一樣,直接在建構式中進行依賴的註入,但是當某個介面有多個實現而且都註冊到了ServiceCollection中,獲取就沒有那麼方便了,您可以用ICodeDiServiceProvider 來幫助您獲取服務實體.

例如,當 ISay 介面有 SayInChinese 和 SayInEnglish兩個實現, 我們我們如何獲取我們想要的服務實體呢?

 


ICodeDiServiceProvider.GetService(string name=null)
引數中的Name支援萬用字元.

CodeDi如何實現的?

既然是一個輕量級工具,那麼實現起來自然不會太複雜,我來說說比較核心的程式碼.

 


GetInterfaceMapping透過反射機制,首先獲取程式集中的所有介面allInterfaces,然後遍歷allInterfaces找到該介面對應的實現,最終,該方法傳回介面和實現的匹配關係,為Dictionary>型別的資料.

 


該方法要判斷CodeDiOptions中是否忽略了該介面,同時,是否指定實現對映關係.
什麼叫實現對映關係呢?參見InterfaceMappings
如果指定了,那麼就按指定的來實現,如果沒指定,就會把每個實現都註冊到ServiceCollection中.

 


AddToService中,要判斷有沒有對介面的生命週期進行配置,參見ServiceLifeTimeMappings,如果沒有配置,就按DefaultServiceLifetime進行配置,DefaultServiceLifetime如果沒有修改的情況下時ServiceLifetime.Scoped,即每個Request建立一個實體.

 


這CodeDiServiceProvider的實現程式碼,這裡參考了依樂祝寫的<.net core=””>給出的一種解決方案,即當某個介面註冊了多個實現,其實可以透過IEnumerable獲取所有的實現,CodeDiServiceProvider對其進行了封裝.</.net>

Enjoy it

只要進行一次簡單的CodeDi配置,以後系統中添加了新的介面以及對應的服務實現後,就不用再去一個個地Add到IServiceCollection中了.

如果有問題,歡迎Issue,歡迎PR.
最後,賞個Star唄! 前往Star

贊(0)

分享創造快樂