一、前言

上一篇大概說了下abp通用樹形模塊如何使用,本篇主要分析下設計思路,
日常開發中會用到很多樹狀結構的資料,比如:產品的多級分類、省市區縣,大多數系統也會用到類似“通用字典/資料字典”的功能,為系統各個地方提下拉框選擇的資料源,abp提供了一個模塊化系統,只要按它的約定就可以實作一個通用的樹形資料的模塊,這樣公司的多個系統都可以使用,也可以用類似nuget的方式提供給別人使用,
先列舉下它的功能
- 通過nuget方便安裝和升級
- 配置簡單
- 默認已經提供“通用字典”功能
- 物體、管理器、應用服務都是抽象類,結合泛型 狠容易擴展實作自己的樹形結構
二、必備知識
這不是abp入門級的文章,是探討系統模塊化開發的一種思路,所以要求對abp有經驗,完整看過abp檔案,對涉及到的模塊、依賴注入、啟動配置、權限、選單、本地化等等概念有清晰的認識
三、包和原始碼
原始碼地址:https://github.com/bxjg1987/abpGeneralModules
nuget:Install-Package BXJG.GeneralTree -Version 1.0.2
在線地址: http://test.cqsifang.com/ 賬號密碼:admin zlj.com (別胡來,拜托...)
原始碼倉庫中還有通用的檔案模塊、附件模塊,后期會講講;nuget搜索bxjg可以找到這幾個相關的包
四、總體設計
為了便于說明,我們以常見的產品無限級分類來說明,所有樹形結構資料有這么幾個特點:
- 有個ParentId屬性指向父級節點,
- 有個code,資料格式類似:00001.00001,一個是能簡單體現產品分類節點的層級結構,二個是方便將來查詢某個分類及其后代分類下的所有產品 where categoryCode like '00001%
- 當然還有Name屬性
上面說了定義物體類的關鍵點,然后我們需要提供一個對應的Manager(這個是abp定義領域服務的套路),來主負責CRUD和節點間的移動操作,其實最麻煩的就是自動處理code,新增和修改時要根據所屬父節點的code自動生成子節點的code,移動時就更復雜了,要重新計算當前節點及其兄弟節點及其所有后代節點的code,這還涉及到目標節點和源節點,為了便于擴展,上面的領域服務還得將被處理的物體泛型話,文章后續會具體說明
最后按abp套路我們還需要提一個應用服務,它核心操作就是呼叫上面提供的Manager位元組點的crud操作,在此基礎上按abp的套路應該提供權限驗證、處理物體與dto之間的轉換,同理為了便于將來模塊的使用方進行擴展,我們應該應用抽象類和泛型的威力,文章后續會具體說明
最后我們如何提供Repository呢?參考abp zero的思路,我們將這個遺留到呼叫方來定義,在我們的領域服務Manager和應用服務AppService中都是通過依賴注入注入的IRepository<TEntity,TKey>
核心的3個東東定義好后,我們分別實作一個默認類,實作一個“通用字典”,將來呼叫方可以繼承我們的類并提供泛型引數來實作他們自己的樹形結構,
另外我們將所有的代碼放在一個專案中,因為模塊足夠小,功能少 這樣呼叫方用起來更方便
注意一點,上面以產品分類來說明只是便于理解,既然要提供擴展能力,設計時只能從抽象的角度來看待樹形資料,否則設計出來的東西很容易最后發現不夠抽象,此廢話只可意會不可言傳
最后是abp相關的:本地化定義、模塊定義及依賴關系、權限提供器、選單提供器、動態webapi的處理
五、物體類
物體類我這里只是說明,具體原始碼請訪問頂部的github
GeneralTreeEntity<TEntity>
它定義了樹形結構資料的通用樹形,Id、Code、Name、Parent等
泛型TEntity是子節點的型別,由于是樹,實際上也是父節點的型別,這種設計是方便將來模塊使用方在實作自定義的樹形結構時拿到的Parent樹形和Children樹形,是他們自己定義的型別
主鍵Id屬性,我定死了long型別,其實也可以使用泛型的TKey,思來想去簡單起見直接定死吧
public class GeneralTreeEntity : GeneralTreeEntity<GeneralTreeEntity>
為了提供我們默認實作的“通用字典”功能,我們定義一個默認的子類GeneralTreeEntity,將來系統中那些簡單的資料可以直接使用它
IsSysDefine表示此節點是否是系統預定義的,將來不允許洗掉
IsTree是否是樹形,將來可能會用到,因為某些下拉框資料可能不需要多層次的,比如:民族,學歷
六、領域服務
按套路我們提供一個抽象的領域服務Manager類,和一個為了實作“通用字典”功能的默認實作
public abstract class GeneralTreeManager<TEntity> : DomainService where TEntity : GeneralTreeEntity<TEntity>
它的主要職責總體設計也說了一嘴,完成crud和move移動操作,難點是處理code的自動生成,尤其是移動節點時,節點原來位置之后的其它節點及其后代節點、目標節點之后的其它節點及其后代節點的code的生成
內部對資料的操作直接注入IRepository<TEntity, long>,因此按abp的套路,默認情況下使用EF時,呼叫方只需要在他的DBContext中頂一個DBSet就可以了
public class GeneralTreeManager : GeneralTreeManager<GeneralTreeEntity>
實作“通用資料字典”的默認領域服類,因為核心功能父類基本都完成了,所以幾乎沒代碼
七、應用服務
按套路一個抽象類,一個默認實作類,內部核心操作是上面提供的Manager來完成的,應用服務主要是出去權限和dto之間的轉換
public class GeneralTreeAppServiceBase< TEntity, TDto, TEditDto> : ApplicationService, IGeneralTreeAppServiceBase<TDto, TEditDto>
where TEntity : GeneralTreeEntity<TEntity>
where TDto : GeneralTreeGetTreeNodeBaseDto<TDto>, new()
where TEditDto : GeneralTreeNodeEditBaseDto
另外它提供了一些通用方法,一個樹形資料通常在3個地方唄使用,以產品分類為例,在產品分類的管理頁面、在產品的搜索欄應該提供產品類別的選擇、在產品編輯頁面應該有個下拉框選擇當前產品所屬類別,其它樹形資料都有類似的場景,因此抽象的應用服務處理了這部分功能
public class GeneralTreeAppService : GeneralTreeAppServiceBase< GeneralTreeEntity, GeneralTreeDto, GeneralTreeEditDt, GeneralTreeManager>,IGeneralTreeAppService
按套路我們為“通用字典”提供了一個默認的實作類
應用服務中的DTO定義、應用服務介面我這里省略了,這是abp的常規套路,請看原始碼
八、abp相關套路:模塊、本地化、權限、選單
模塊和本地化就不說了,abp的常規套路
由于我們提供了“通用字典”,默認情況下是可以直接用作你專案的,呼叫方完全可以按abp的套路在自己的模塊中來配置權限和選單,但是默認我們的模塊也提供了,呼叫方完全可以在主機的PermissionProvicer和NavigationProvider的合適的位置配置權限和選單,參考GeneralTreeModuleConfig原始碼
九、總結
abp本身提供了模塊化方式,如果運用得當我們的系統可以由很多小模塊組成,將來更容易維護、升級和復用
就好比我們目前提供的通用樹,如果你使用的是abp,那么完全可以拿去就用,類似的“通用附件”模塊,因為我們的多個系統或者同一個系統都可能會用到附件的功能,到處復制代碼是下下策,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/2951.html
標籤:ASP.NET
上一篇:Net專案添加 WebAPI
