日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

未能加载文件或程序集rsy3_abp vnext2.0之核心组件模块加载系统源码解析

發(fā)布時(shí)間:2024/1/23 windows 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 未能加载文件或程序集rsy3_abp vnext2.0之核心组件模块加载系统源码解析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

abp vnext是abp官方在abp的基礎(chǔ)之上構(gòu)建的微服務(wù)架構(gòu),說(shuō)實(shí)話,看完核心組件源碼的時(shí)候,很興奮,整個(gè)框架將組件化的細(xì)想運(yùn)用的很好,真的超級(jí)解耦.老版整個(gè)框架依賴Castle的問(wèn)題,vnext對(duì)其進(jìn)行了解耦,支持AutoFac或者使用.Net Core的默認(rèn)容器.vnext依然沿用EF core為主,其余ORM為輔助的思想,當(dāng)然EF core來(lái)實(shí)現(xiàn)DDD確實(shí)有優(yōu)勢(shì),EventBus提供了分布式版本,并提供了RabbitMQ的實(shí)現(xiàn)版本,Aop攔截器依然采用Castle.Core.AsyncInterceptor.這一點(diǎn)Dora.Interception貌似可以解決,估計(jì)如果高度組件化,那么這也是一個(gè)擴(kuò)展點(diǎn).整個(gè)模塊加載系統(tǒng)更加的完善,提供了跟多可選擇的特性,工作單元也進(jìn)行了小幅度的重構(gòu),代碼更加的通俗易懂(在實(shí)現(xiàn)異步工作單元嵌套的設(shè)計(jì)就有體現(xiàn))等等還有很多,當(dāng)然不是本文的重點(diǎn),vnext2.0是個(gè)值得使用的框架.下面開(kāi)始回到正題.

1、模塊加載系統(tǒng)

模塊加載系統(tǒng)算是vnext的整個(gè)框架的入口,離了他,這個(gè)框架就廢了.具體它有什么作用,看下面的代碼分析,模塊加載系統(tǒng)的入口如下:

?每個(gè)應(yīng)用框架必須要有一個(gè)啟動(dòng)模塊類型,可以通過(guò)泛型或者Type實(shí)例傳入,并且給定啟動(dòng)參數(shù).

啟動(dòng)模塊類型:雖然上面給定的約束是必須實(shí)現(xiàn)IAbpModule,但是大多數(shù)的實(shí)現(xiàn)情況是

暫時(shí)不講?AbpModule的源碼,后面分析到具體的流程再做介紹.

ok,看看AbpApplicationFactory工廠做了什么了,通過(guò)名字分析很明顯.AbpApplication的工廠.

分析這個(gè)方法就能得出,只要傳入啟動(dòng)模塊的類型和DI的ServiceCollection和啟動(dòng)應(yīng)用的參數(shù),就能構(gòu)建一個(gè)IAbpApplicationWithExternalServiceProvider,那么看看IAbpApplicationWithExternalServiceProvider都有什么

?構(gòu)建完成基本的實(shí)體后,調(diào)用Initialize方法初始化框架.再看看IAbpApplication接口

?包含啟動(dòng)模塊類型,DI注入集合、DI服務(wù)提供類,以及一個(gè)關(guān)閉應(yīng)用程序必須執(zhí)行的ShutDown方法.在看看IModuleContainer

?包含模塊集合,在Abp中,模塊代表一個(gè)程序集.這里就是啟動(dòng)abp vnext框架的啟動(dòng)模塊類型所依賴的所有模塊類型,即所有的程序集集合你可以這樣理解.因?yàn)橐粋€(gè)Module類型(繼承AbpModule類型或者實(shí)現(xiàn)IAbpModule接口的類型)代表一個(gè)程序集.且一個(gè)程序集只有一個(gè)Module類型(繼承AbpModule類型或者實(shí)現(xiàn)IAbpModule接口的類型).

ok,接著回到上面的代碼

?此處省略一些無(wú)關(guān)核心流程的代碼,代碼如下:

?簡(jiǎn)單的一些非空校驗(yàn),這里有一個(gè)非常有趣的設(shè)計(jì),如下:

繼續(xù)查看,如下

?

?ObjectAccessor源碼如下:

?類似裝飾者模式,內(nèi)部容納一個(gè)類型.最后

?ok,到這里整個(gè)流程大致就是,給IServiceProvider創(chuàng)建一個(gè)ObjectAccessor,且ObjectAccessor沒(méi)有Value值,同時(shí)將ObjectAccessor寫入DI,并做了簡(jiǎn)單的搜索優(yōu)化.關(guān)于IServiceProvider的ObjectAccessor的作用,暫時(shí)不介紹,后續(xù)會(huì)說(shuō).

接著看如下代碼:

?初始化外部設(shè)置參數(shù),接招向DI中注入IAbpApplication和IModuleContainer的單例對(duì)象.

接著看下面的代碼:

?

注入配置文件、日志、國(guó)際化等服務(wù).接著看AddCoeAbpServices方法

?

注入ModuleLoader(處理程序集間依賴關(guān)系,處理模塊加載生命周期、的核心類型)、程序集發(fā)現(xiàn)類(所有程序集都能通過(guò)該類型拿到,只要程序集加入到了框架)、類型發(fā)現(xiàn)類(程序集集合所包含的所有類型)

?初始化配置文件系統(tǒng)、等等操作,接著看如下代碼,將上述類型寫入DI

?接下去這行代碼就有趣了,如下:

看看它干了什么,如下:

?看看?services.GetConventionalRegistrars干了什么,如下:

?很明顯,從DI中讀取程序集注冊(cè)規(guī)則類列表,如果沒(méi)有,則寫入默認(rèn)的程序集注冊(cè)規(guī)則類.所以,這里如果你想自定義程序集注冊(cè)規(guī)則,那么只需在有效的應(yīng)用程序加載生命周期階段注入自定義的程序集注冊(cè)類即可,該類型必須實(shí)現(xiàn)下圖所示接口

?ok,這個(gè)擴(kuò)展點(diǎn)講完之后,看看默認(rèn)的程序集注冊(cè)規(guī)則類DefaultConventionalRegistrar干了什么,如下:

?

?很簡(jiǎn)單,自行閱讀,再看看AddType的實(shí)現(xiàn),如下:

?

?支持類型跳過(guò),如果類型打了DisableConventionalRegistrationAttribute特性,那么該類型將不會(huì)被寫入DI.

?如果當(dāng)前類型沒(méi)有打DependencyAttribute,或者打了DependencyAttribute特性,沒(méi)有設(shè)置Lifetime,則當(dāng)前類型也不會(huì)寫入DI.

這里注意,根據(jù)代碼可以發(fā)現(xiàn),abp給類型生命周期的方式有兩種,老版只有一種,如下:

第一種:

?通過(guò)實(shí)現(xiàn)ISingletonDependency(單例注入),ITransientDependency(普通引用類型),IScopedDependency(范圍內(nèi)唯一)三大接口來(lái)表示當(dāng)前類型的生命周期,老版abp也是使用這種方式,但是沒(méi)有IScopedDependency

第二種:

?

?通過(guò)DependencyAttribute特性,結(jié)構(gòu)如下

接著,如下代碼

?如果當(dāng)前類型打了ExposeServicesAttribute特性,那么則會(huì)調(diào)用該特性的如下方法

?這個(gè)方法的用途是找出如果我們需要從DI中釋出個(gè)類型,可以使用哪幾種方式(常用的是接口,自身等),示例代碼如下:

?那么如果需要在框架中使用TestClass的實(shí)現(xiàn),可以用ITestClass接口進(jìn)行依賴注入,因?yàn)?/p>

?當(dāng)然這里可以寫多個(gè),因?yàn)?/p>

?ExposeServicesAttribute特性中的IncludeDefaults和IncludeSelf屬性是默認(rèn)的策略,

IncludeDefaults設(shè)置為true是根據(jù)類型找出其實(shí)現(xiàn)的接口,且接口必須以I字母開(kāi)頭,且接口后面的名字必須和當(dāng)前類型相等.如果匹配那么該接口有效,也可以進(jìn)行依賴注入.

IncludeSelf設(shè)置為true,則可以通過(guò)當(dāng)前類型進(jìn)行依賴注入.

接著看如下代碼

?

?很簡(jiǎn)單,只需在有效的應(yīng)用程序加載生命周期階段注入指定的Action,注入方式如下:

使用例子,類型映射,如下:

最后看如下代碼

這段代碼很簡(jiǎn)單,就不解釋了.DependencyAttribute特性給上對(duì)應(yīng)的值就能執(zhí)行指定的操作,ok,到這里總結(jié)一下這種設(shè)計(jì)的用處,非常nice,原先老版abp注冊(cè)系統(tǒng)核心單例類型是依賴castle的,如果換成這種設(shè)計(jì)方式,更加的靈活,如果我們需要給底層添加一個(gè)核心類,只需要?jiǎng)?chuàng)建一個(gè)類,然后配合Dependency特性和ExposeServices特性即可和DI完美集合,同時(shí)還提供了Action擴(kuò)展,讓你可以干很多的事情,就這一點(diǎn),比老版abp好太多.到這里DefaultConventionalRegistrar介紹完畢

ok,在回到AddCoreAbpServices方法,如下:

?這里也很簡(jiǎn)單,向DI中預(yù)先寫入AbpModuleLifecycleOptions,該參數(shù)用于控制模塊加載的生命周期,這四個(gè)Contributor分別對(duì)應(yīng)模塊加載生命周期的接口,

?

?

?

?再看看核心Module的抽象

?到這里肯定很多人很困惑,所以這里跳過(guò)一些流程,看下ModuleManager如何處理,如下

?釋出Contributor集合

?

Contributor的作用很明顯,模塊加載生命周期中你可以執(zhí)行的一些方法.這些方法會(huì)拿到一個(gè)ServiceProvider,即你可以操作DI,完成一些關(guān)鍵服務(wù)的操作.

關(guān)于模塊加載的生命周期方法有哪些,如下

?每個(gè)接口對(duì)應(yīng)一個(gè)生命周期,這和老版Abp的設(shè)計(jì)也完全不同.優(yōu)缺點(diǎn)暫時(shí)沒(méi)發(fā)現(xiàn).

接著,如下:

?調(diào)用ModuleLoader單例實(shí)例,執(zhí)行加載模塊的方法.核心算法和老版Abp一樣,這里稍微解釋下,

?核心點(diǎn)如下:

(1)、加載啟動(dòng)模塊所有依賴的模塊,并設(shè)置依賴項(xiàng),最后生成IAbpModuleDescriptor集合

?(2)、模塊進(jìn)行拓?fù)渑判?進(jìn)行循環(huán)依賴檢測(cè)

?ok,下面開(kāi)始解析核心點(diǎn)源碼

通過(guò)DependsOnAttribute特性來(lái)處理模塊間的依賴關(guān)系.核心代碼如下:

?拿到當(dāng)前類型的DependsOnAttribute特性,解析其內(nèi)部的類型,加入到dependencies依賴類型集合.所以表示模塊間的依賴關(guān)系根據(jù)如上代碼可以得出兩種模式,如下:

?常用的是第二種.

通過(guò)上面的方法拿到所有的依賴類型集合之后,執(zhí)行下面的遞歸方法

?這樣就可以遍歷出所有的啟動(dòng)模塊以來(lái)的所有模塊.同時(shí)去除了重復(fù)的模塊.最后遍歷所有的模塊生成如下類型的實(shí)例

?模塊實(shí)例的生命周期為單例,如下圖:

接著開(kāi)始處理啟動(dòng)參數(shù)中配置的插件模塊

?

?插件模塊的三種添加方式如下

public static class PlugInSourceListExtensions
{
public static void AddFolder(
[NotNull] this PlugInSourceList list,
[NotNull] string folder,
SearchOption searchOption = SearchOption.TopDirectoryOnly)
{
Check.NotNull(list, nameof(list));
list.Add(new FolderPlugInSource(folder, searchOption));
}
public static void AddTypes(
[NotNull] this PlugInSourceList list,
params Type[] moduleTypes)
{
Check.NotNull(list, nameof(list));
list.Add(new TypePlugInSource(moduleTypes));
}
public static void AddFiles(
[NotNull] this PlugInSourceList list,
params string[] filePaths)
{
Check.NotNull(list, nameof(list));
list.Add(new FilePlugInSource(filePaths));
}
}

這邊只介紹一種,其余核心流程都一樣,如下:

FolderPlugInSource添加插件類型,其核心參數(shù)如下:

直接給文件夾路徑+名稱,掃描下面的插件程序集,并進(jìn)行程序集過(guò)濾,核心的過(guò)濾方法如下:

?最后,返回實(shí)現(xiàn)了AbpModule的核心模塊類型

?ok,接著回到模塊加載系統(tǒng)的加載插件方法,如下:

?

?ok,這里可以發(fā)現(xiàn)亮點(diǎn)

1、你可以同時(shí)添加多種形式的插件宿主,可以是文件夾下所有的插件程序集、可以是程序集解決方案、也可以是一個(gè)指定的程序集文件.Abp暫時(shí)提供了這三種,當(dāng)然如果你有實(shí)力,也可以編寫遠(yuǎn)程調(diào)用程序集插件.

2、和模塊加載系統(tǒng)完成了集成,和上面的流程一樣,加載出所有啟動(dòng)模塊依賴的類型,并寫入DI

?ok,到這里插件模塊介紹完畢.最后和普通模塊一樣生成IAbpModuleDescriptor集合

接著,拿到所有的模塊集合之后(包括插件),開(kāi)始設(shè)置所有模塊間的依賴關(guān)系,如下,細(xì)心的會(huì)發(fā)現(xiàn)上面的

?中有依賴集合.下面的代碼就是整理這個(gè)關(guān)系的.

?這里,邏輯很簡(jiǎn)單,就不介紹了,直接跳過(guò),主要是通過(guò)DependsOnAttribute特性來(lái)實(shí)現(xiàn).

接下去介紹核心點(diǎn)二模塊進(jìn)行拓?fù)渑判?進(jìn)行循環(huán)依賴檢測(cè)

此時(shí),我們拿到了一個(gè)完整的模塊集合,內(nèi)部的依賴關(guān)系也已經(jīng)初步執(zhí)行好.

?核心代碼如下,關(guān)于拓?fù)渑判?算法的核心邏輯自行查閱代碼,主要內(nèi)容是按照依賴關(guān)系依次加入到集合,后期可一次執(zhí)行,這樣就可以集成生命周期),防止循環(huán)依賴就不說(shuō)了,接著,將啟動(dòng)模塊放到最后為了配合模塊生命周期方法的執(zhí)行.

ok,到這里兩個(gè)核心點(diǎn)介紹完畢.

接下去.如下代碼

?

?生成如下上下文,并單例寫入DI

這個(gè)Item屬性醉了,個(gè)人感覺(jué)沒(méi)什么用,因?yàn)橄旅孢@個(gè)for循環(huán)

?接著執(zhí)行如下代碼

?所以這兩個(gè)生命周期接口執(zhí)行的時(shí)間節(jié)點(diǎn)一定要記住.同時(shí)上下文會(huì)給你DI容器,方便你進(jìn)行任何必須的類型操作.

接著

?將當(dāng)前模塊類型對(duì)應(yīng)的程序集中所有的類型寫入DI,默認(rèn)的注入規(guī)則上面已經(jīng)介紹,默認(rèn)的注冊(cè)器類型為DefaultConventionalRegistrar.同時(shí)執(zhí)行生命周期接口IZcfModule.

到這里已經(jīng)執(zhí)行的三個(gè)模塊生命周期接口如下:

?切記其執(zhí)行的節(jié)點(diǎn).

?接著開(kāi)始初始化模塊系統(tǒng),注意,這邊我跳過(guò)了DI容器切換的的內(nèi)容(關(guān)于DI容器切換的源碼分析后續(xù)的博文會(huì)介紹),代碼如下:

?從DI中釋出單例ModuleManager類,執(zhí)行如下初始化方法

?這段代碼進(jìn)行簡(jiǎn)單的模塊加載日志記錄,后面的核心代碼上面說(shuō)過(guò),執(zhí)行預(yù)定義的模塊生命周期方法,對(duì)應(yīng)如下接口:

執(zhí)行這四個(gè)接口必須實(shí)現(xiàn)的方法,當(dāng)然在AbpModule中都以virtual標(biāo)記,所以你可以按照順序一次進(jìn)行一些類型操作.但是這幾個(gè)生命周期函數(shù),上下文只提供ServiceProvider,

功能做了限制.其余三個(gè)生命周期接口提供的是IServiceCollection實(shí)例,所以他們之間還是有差別的,除了執(zhí)行順序之外.

ok,到這里abp vnext2.0的核心模塊記載系統(tǒng)核心流程源碼分析結(jié)束了,純屬個(gè)人理解,能力有限,有問(wèn)題請(qǐng)指正!

下一篇會(huì)介紹vnext如何完成整個(gè)DI切換,換成autofac或者其他容器.以及如何和模塊加載系統(tǒng)結(jié)合.

總結(jié)

以上是生活随笔為你收集整理的未能加载文件或程序集rsy3_abp vnext2.0之核心组件模块加载系统源码解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。