Prism 原始碼解讀3-Modules載入
阿新 • • 發佈:2020-03-31
## 介紹
在軟體開發過程中,總想元件式的開發方式,各個元件之間最好互不影響,獨立測試。Prism的Modules很好的滿足了這一點。
![](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225558301-1721489782.png)
這個架構圖很好了講解了Prism的Modules的概念
Prism支援通過配置檔案,資料夾,手動載入Module的方式,並且對Module的載入進行驗證,包括重複和迴圈依賴驗證
Prism載入模組的順序
![](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225612587-1306769571.png)
直接看原始碼吧
## 0、Modules載入
- Modules的載入主要依靠ModuleCatalog來發現模組,
- 通過ModuleManager來載入模組並對模組進行驗證以確保模組的載入順序,
- ModuleInitializer負責模組的初始化,包括載入模組所必須的類和顯示UI Elements等等。
在Prism.PrismApplicationBase 的Initialize方法中呼叫
![1585574598775](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538616-888557047.png)
建立目錄
![1585574672183](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538631-62486994.png)
RegisterRequiredTypes方法中向容器注入ModuleManager,ModuleInitializer,
![1585574816406](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538630-837257643.png)
最後呼叫了InitializeModules方法,並在其中呼叫了ModuleManager的Run方法
![1585574852698](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538632-31279662.png)
看著兩個名字就明白了,第一個是發現模組並驗證模組,第二個是載入模組並初始化。
![1585574917778](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538632-592136262.png)
看一下ModuleCatalogBase的Initialize方法,果然
![1585574973443](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538631-1192325281.png)
![1585574987953](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538632-128845162.png)
而驗證就更加有意思了
![1585575114834](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538633-1899228799.png)
重複性驗證
![1585571571246](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538654-269099109.png)
通過模組名字ModuleNames來判斷是否被載入過,,如果存在就丟擲異常
載入順序驗證
![1585572866324](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538654-954393316.png)
同時看一下ModuleBase
![1585575240730](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538663-1116753081.png)
每當items發生變化都會進行驗證
![1585575308583](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538664-1413530195.png)
![1585575327939](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538665-1992457638.png)
發現驗證完了來看一下ModuleManage的LoadModulesWhenAvailable方法
![1585575416018](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538682-60870506.png)
![1585575456472](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538684-2061302146.png)
![1585575508444](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538736-1459788632.png)
![1585575521164](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538741-1724278222.png)
看到最終使用了ModuleInitializer來初始化Module。其過程通過Linq實現延遲載入技術。
![1585575588013](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538749-124345976.png)
在這個方法中發現Module必須實現IModle介面。並在這兒呼叫了RegisterTypes和OnInitialized方法。
模組的載入看完了,下面來看例子吧
## 1、通過AppSetting載入
先看一下配置檔案
![1585575781099](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538835-2082653511.png)
在初始化時
![1585575803440](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538844-577539271.png)
看到重寫了CreateModuleCatalog,前面已經介紹過ModuleCatalog就是控制Module發現和驗證的。
![1585575869468](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538846-362450134.png)
![1585575909447](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538848-265482678.png)
![1585575962111](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538887-2124780552.png)
可以看到section的名稱必須是modules。
先解析Module依賴邏輯,最後呼叫AddModule方法
![1585577943221](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538897-1580856103.png)
再ModuleAModule中載入相關的UIElement。
## 2、通過程式碼載入
通過程式碼載入就更簡單了,直接在ConfigureModuleCatalog方法中呼叫預設的ModuleCatalog載入相關的Module就可以了。
![1585578152349](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538906-996983112.png)
在ModuleAModule中程式碼不變
這其中的邏輯在0節中已經解釋清楚了,就不在敘述。
## 3、通過目錄載入
通過目錄載入,如果不看原始碼怎麼設計,需要建立一個ModuleCatalog,在建立的時候將目錄地址傳入。在內部InnerLoad方法中找到對應目錄,然後通過遍歷程式集找到實現IModule介面的類,載入這個類就可以了。
看了下原始碼也正是這麼做的
![1585578439577](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538909-1978538547.png)
![1585578580233](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538939-1155877340.png)
看了原始碼發現官方考慮了更多的問題,比如建立了AppDoamin來載入程式集以保證隔離和資料安全。甚至還為其建立了一個InnerModuleInfoLoader類來反射程式集
![1585578854546](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225538941-441699435.png)
這樣的指責分配非常好,我們甚至可以寫一個通過網路來載入Module的ModuleCatalog類。
## 4、通過手動方式載入
![1585579279370](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225539051-1205963972.png)
先在ConfigureModuleCatalog中將所有的Module載入進來,並將InitializationMode的方式設定為按需,
![1585579366391](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225539059-1389352781.png)
那麼就可以在需要的時候利用LoadModule方法載入之前載入的Module
![1585579427491](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225539071-622200833.png)
![1585579463038](https://img2020.cnblogs.com/blog/1078802/202003/1078802-20200330225539086-1037128174.png)
值得注意的是並沒有提供解除安裝Module的介面。
## 總結
這一篇介紹了下Modules載入的原理,其實就是
- ModuleCatalog負責發現Module。
- 通過ModuleManager來載入模組並對模組進行驗證以確保模組的載入順序,
- ModuleInitializer負責模組的初始化,包括載入模組所必須的類和顯示UI Elements等等。
下一篇開始將介紹MVVM的