談到模組大家應該都不會感到陌生,不管是前端還是後端都有模組的概念,XAF中的模組概念與大多數框架中的模組概念是相通的。XAF模組首先是一個.NET類庫,同時它還包含一個繼承自ModuleBase的Module類,Module類主要用於收集及對外暴露模組中的一些資源(BusinessObject、Controller、Action、Model、PropertyEditort等),同時XAF模組間的依賴與.NET類庫間的依賴也是一致的,比如:A模組依賴B模組,B模組依賴C模組,那A模組同時擁有了B模組與C模組所提供的資源。XAF模組涵蓋的功能很多,當前只對模組的部分功能進行介紹,後續還會與其它的概念一起介紹。
XAF預設提供了大量的基礎功能模組(審計、圖表、儀表盤、驗證、報表、狀態機等),你可以根據需要將這些模組新增到你的專案中。
XAF專案主要包含應用程式專案與模組專案,當然也可以包含普通的.NET專案。應用程式專案是負責專案的啟動,所以它需要指定平臺(WinForm與Blazor),模組專案在不依賴特定平臺時,是可以被其它應用程式專案或其它模組專案參照,依賴特定平臺後,只能被特定平臺的專案參照。
在XAF22.1之前的版本中,XAF專案中包含兩種模組專案型別,一種是與平臺相關的,一種是不相關的,在之後的版本中,將平臺相關的模組程式碼移到了應用程式專案中,目的是為了簡化專案結構。如果你想建立獨立的模組,並且模組中包含了不同平臺的程式碼,你還是需要建立平臺相關的模組專案。
模組註冊分為兩種,一種是模組間依賴的註冊,一種是將模組註冊到應用程式專案中,這兩種註冊方式是不一樣的。
在整個XAF專案啟動過程中模組是最先被初始化的,這裡要引出一個概念Application(在不同的平臺會有不同的實現,它們都是XafApplication的子類),從名字你就可以看出它在XAF中的地位,它上面掛載了執行XAF所需的所有資源,XAF模組當然也在其中,同時它還提供了豐富的功能,在WinForm專案中Application是以單例形式存在的,在Blazor專案中每一個對談都會有一個Application範例,現在你可以簡單將Application理解為整個XAF應用的中心,後面會對它進行單獨的介紹。
在XAF22.1後,將模組註冊到應用程式專案中WinForm與Blazor採用了相同的設定方式,下面以WinForm為例
上面的程式碼是ApplicationBuilder類中的片段,在XAF22.1後,WinForm專案都會存在一個ApplicationBuilder類,它是用於構建Application範例。接觸過XAF的小夥伴對上面的程式碼應該比較容易理解,這裡簡單的解讀一下,builder是IXafApplicationBuilder<TBuilder>的一個範例,在不同的平臺(WinForm與Blazor)會有不同的實現。
builder.Modules是專門用於將模組註冊到應用程式專案中的,它上有一個Add方法可以方便對模組進行註冊,當然你也可以基於Add方法再作進一步的封裝,例如:AddConditionalAppearance(ConditionalAppearance模組的註冊方法),註冊模組的先後順序並不影響模組的載入。
在之前的XAF版本中,將模組註冊到應用程式專案中,都是將模組中Module類的範例新增到Application.Modules中,新的註冊方式可讀性更強,目的是相同的,但將模組新增到Application.Modules中是在builder.Build()時執行的。
builder範例中包含一個_buildSteps委託集合,呼叫builder上的方法也就是向_buildSteps集合中新增委託(Action<XafApplication>),委託有一個Application引數,借用此引數可以對Application進行設定,最後的builder.Build()是將_buildSteps集合中的委託遍歷並執行,並返回Application的一個範例。下面是Build方法簡化後的程式碼
在模組註冊到應用程式專案中時可以對模組進行設定,如果是自己的模組,首先需要在模組的Module類中新增對應的屬性,如Test,在註冊時直接給模組屬性賦值,如下面的程式碼。如何使用模組Module類中的屬性,將在後面進行介紹
如果你的模組是對外發布的,想更嚴謹一些,你可以參考XAF內部模組的做法,單獨建立一個Options類,通過Options類收集模組設定,避免使用者直接給Module類中的屬性賦值
在前面的介紹中,大家應該已經知道模組的依賴與.NET類庫的依賴是相似的。一個XAF模組想依賴另一個XAF模組,首先要參照這個被依賴模組的類庫,並在Module類別建構函式中,將被依賴模組中Module類的型別新增到RequiredModuleTypes中,程式碼如下:
由於RequiredModuleTypes的初始值是來自GetRequiredModuleTypesCore方法,所以我們也可以在Module類中重寫GetRequiredModuleTypesCore方法來實現相同的操作,程式碼如下:
在上面的程式碼中,模組註冊的先後順序是不影響後續操作的,甚至依賴模組被無意中重複新增了,也不會有任何影響,因為模組在被正式載入時,會進行相應的過濾,當然最好不要這樣做,下面的程式碼是可以正常執行的
模組載入是在builder.Build()時進行的,模組載入的核心邏輯是放在ModuleList類中的。
這裡簡單說一下它的載入邏輯,ModuleList會先載入通過builder在應用程式專案中註冊的模組,然後再去載入已載入模組的依賴模組,依賴模組再去載入自身的依賴模組,這裡是一個遞迴,當然在載入過程中ModuleList會判斷如果已被載入則跳過,最終會保證ModuleList中每一個模組型別只有一個模組範例,這裡的ModuleList就是Application.Modules,你可以通過Application.Modules獲取被載入的所有模組範例。
ModuleList類上有一個FindModule方法,可以使用它通過模組型別查詢模組範例,那我們就可以在能夠存取到Application的情況下,呼叫Application.Modules.FindModule查詢模組範例,就可以存取到模組中的屬性。
模組在XAF中是一個比較重要的概念,模組中還很多知識點,這裡只介紹了模組的註冊與載入,在後續還會結合其它概念再介紹,同時還要注意在XAF22.1後,XAF專案結構進行了簡化,同時模組在應用程式專案中的註冊方式也不一樣了。
注意:本系列文章只是講解XAF中常用到的概念,方便大家理解,具體的操作方法還是需要參考官方檔案