.net core依赖注入的封装
現(xiàn)在流行的系統(tǒng)一般都采用依賴(lài)注入的實(shí)現(xiàn)方式,利用DI容器來(lái)直接獲取所用到的類(lèi)/接口的實(shí)例。.net core也一樣采用DI的方式,提供了DI容器的接口IServiceCollection,并提供了基于該接口的缺省實(shí)現(xiàn)ServiceCollection。
這樣我們就可以不再像以前一樣,需要引入第三方的Untiy、Autofac、Castle等DI組件了。
在.net core源碼的ServiceCollectionExtensions的實(shí)現(xiàn)中,有三個(gè)注冊(cè)的方法AddScoped、AddSingleton、AddTransient。這其中的三個(gè)選項(xiàng)(Singleton、Scoped和Transient)體現(xiàn)三種對(duì)服務(wù)對(duì)象生命周期的控制形式。
Singleton:ServiceProvider創(chuàng)建的服務(wù)實(shí)例保存在作為根節(jié)點(diǎn)的ServiceProvider上,所有具有同一根節(jié)點(diǎn)的所有ServiceProvider提供的服務(wù)實(shí)例均是同一個(gè)對(duì)象。適合于單例模式。
Scoped:ServiceProvider創(chuàng)建的服務(wù)實(shí)例由自己保存,所以同一個(gè)ServiceProvider對(duì)象提供的服務(wù)實(shí)例均是同一個(gè)對(duì)象。 可以簡(jiǎn)單的認(rèn)為是每請(qǐng)求(Request)一個(gè)實(shí)例。
Transient:針對(duì)每一次服務(wù)提供請(qǐng)求,ServiceProvider總是創(chuàng)建一個(gè)新的服務(wù)實(shí)例。 每次訪(fǎng)問(wèn)時(shí)被創(chuàng)建,適合輕量級(jí)的,無(wú)狀態(tài)的服務(wù)。
這個(gè)具體說(shuō)起來(lái)就太多了,還是查閱相關(guān)材料吧J
?
有了DI容器,我們?cè)谑褂脮r(shí),可以簡(jiǎn)單的在Startup.cs程序中編寫(xiě)上注冊(cè)語(yǔ)句,下面以操作日志的倉(cāng)儲(chǔ)類(lèi)為例:
public void ConfigureServices(IServiceCollection services){
services.AddScoped<IOperLogRepository, OperLogRepository>();
}
?第一個(gè)泛型類(lèi)型表示將要從容器中請(qǐng)求的類(lèi)型(通常是一個(gè)接口)。第二個(gè)泛型類(lèi)型表示將由容器實(shí)例化并且用于完成這些請(qǐng)求的具體類(lèi)型。
?
我們?cè)诓僮魅罩镜倪壿嫹?wù)類(lèi)使用操作日志的倉(cāng)儲(chǔ)時(shí),就這樣寫(xiě):
public partial class OperLogAppService : IOperLogAppService{
private IOperLogRepository service;
public OperLogAppService(IOperLogRepository service)
{
this.service = service;
}
public void Write(OperLogDto operLogDto)
{
this.service.Insert(operLogDto.AsInfo());
}
}
?系統(tǒng)會(huì)在創(chuàng)建OperLogAppService的實(shí)例時(shí),會(huì)自動(dòng)創(chuàng)建IOperLogRepository在DI容器中注冊(cè)O(shè)perLogRepository類(lèi)的實(shí)例。
然而這種方式在框架中是有些不方便的。我們知道,框架要求的是可擴(kuò)展,可配置,在新增系統(tǒng)功能模塊時(shí),還需要手工修改程序,在Startup.cs的ConfiguraeService中增加注冊(cè)(就算把所有注冊(cè)移到一個(gè)獨(dú)立的方法中也是一樣),就如同第一個(gè)代碼寫(xiě)的一樣,包括注冊(cè)倉(cāng)儲(chǔ)類(lèi)、注冊(cè)邏輯服務(wù)類(lèi)等等。然后編譯,再發(fā)布運(yùn)行。每增加、修改一個(gè)模塊,都需要整個(gè)系統(tǒng)編譯、發(fā)布,對(duì)運(yùn)行中的系統(tǒng)影響還是挺大的。
我們的做法是,功能模塊都有一個(gè)自注冊(cè)的類(lèi)。這個(gè)自注冊(cè)的類(lèi)會(huì)將功能模塊中所有的倉(cāng)儲(chǔ)類(lèi)、邏輯服務(wù)類(lèi)等都注冊(cè)進(jìn)DI容器中。Startup.cs會(huì)自動(dòng)查找所有功能模塊中的自注冊(cè)類(lèi),然后將相關(guān)內(nèi)容注冊(cè)進(jìn)DI容器中。這樣就可以做到,每增加一個(gè)模塊,只需要將該模塊的應(yīng)用程序集Dll復(fù)制到系統(tǒng)的運(yùn)行目錄就行了,其他的系統(tǒng)幫你搞定。
按照上述思路,首先是建一個(gè)自注冊(cè)的類(lèi)。這個(gè)類(lèi)都抽象出一個(gè)接口IServiceRegister
public interface IServiceRegister{
/// <summary
/// 注冊(cè)
/// </summary>
void Register(IServiceCollection services);
}
?
我們以通用模塊為例子,自注冊(cè)的類(lèi)應(yīng)該是這樣的。
public class CommonServiceRegister : IServiceRegister{
public void Register(IServiceCollection services)
{
services.AddDbContext<CommonDbContext>(option =>
option.UseDb<CommonDbContext>(services.BuildServiceProvider()),
ServiceLifetime.Scoped);
services.AddScoped<IParaReferRepository, ParaReferRepository>();
services.AddScoped<IParaReferAppService, ParaReferAppService>();
services.AddScoped<ISystemParameterRepository, SystemParameterRepository>();
services.AddScoped<ISystemParameterAppSer
這個(gè)類(lèi)中service.AppScoped注冊(cè)的是倉(cāng)儲(chǔ)層和邏輯層接口對(duì)應(yīng)的實(shí)現(xiàn)類(lèi),我們這里只是列出了系統(tǒng)參數(shù)和引用參數(shù)的注冊(cè)。對(duì)于第一句AddDbContext,請(qǐng)參見(jiàn):4.4 異構(gòu)、多數(shù)據(jù)庫(kù)的存取組件
為了在Startup.cs中自己查找并調(diào)用這些注冊(cè)類(lèi),還是比較簡(jiǎn)單的,程序如下:調(diào)用ReflectionHelper的GetSubTypes方法,獲取所有繼承IServiceRegister的實(shí)現(xiàn)類(lèi),對(duì)于每個(gè)實(shí)現(xiàn)類(lèi),創(chuàng)建實(shí)例并將模塊的倉(cāng)儲(chǔ)和邏輯服務(wù)注冊(cè)到DI容器中。ReflectionHelper的GetSubTypes方法,請(qǐng)參見(jiàn):4.1 反射工具
IEnumerable<Type> serviceList = ReflectionHelper.GetSubTypes<IServiceRegister>();foreach (Type type in serviceList)
{
IServiceRegister register = ReflectionHelper.CreateInstance(type)
as IServiceRegister;
register.Register(services);
}
?
.net framework也可以按照上述思路進(jìn)行,不同的就是.net framework沒(méi)有startup.cs,只需要將上面的內(nèi)容寫(xiě)進(jìn)global.asax即可,還有一點(diǎn)不同是IServiceCollection,可以使用Unity等DI組件提供的DI容器。
原文地址:http://www.cnblogs.com/BenDan2002/p/6087893.html
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺(tái)或掃描二維碼關(guān)注
總結(jié)
以上是生活随笔為你收集整理的.net core依赖注入的封装的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: asp.net core mvc剖析:K
- 下一篇: Azure SQL的DTU和eDTU到底