前言:很久沒更新博客了,天天被該死的業務纏身,今天正好一個模塊完成了,繼續來完善咱們的代碼。以前的六篇完成了領域層、應用層、以及基礎結構層的部分代碼,這篇打算搭建下UI層的代碼。css
DDD領域驅動設計初探系列文章:html
在DDD裏面,UI層的設計也分爲BS和CS,本篇仍是以Web爲例來講明。咱們的Web採用的是MVC+bootstrap的架構。Table組件使用的是bootstrap table,之因此用它是由於它的API比較全,而且博主以爲它的風格適用於各類類型的設備,不管是PC端仍是手機端都都能很好的兼容各類瀏覽器。前端
這裏仍是貼出bootstrap API的相關地址。git
Bootstrap中文網:http://www.bootcss.com/ github
Bootstrap Table Demo:http://issues.wenzhixin.net.cn/bootstrap-table/index.htmlexpress
Bootstrap Table API:http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/編程
Bootstrap Table源碼:https://github.com/wenzhixin/bootstrap-tablebootstrap
Bootstrap DataPicker:http://www.bootcss.com/p/bootstrap-datetimepicker/瀏覽器
上篇完成了WCF的設計代碼,可是具體的業務邏輯的代碼尚未,咱們先來實現具體業務的CURD代碼。
/// <summary> /// 權限管理模塊接口契約 /// </summary> [ServiceContract] [ServiceInterface] public interface IPowerManageWCFService { #region 用戶管理 [OperationContract] List<DTO_TB_USERS> GetUsers(ExpressionNode expressionNode); [OperationContract] DTO_TB_USERS AddUser(DTO_TB_USERS oUser); [OperationContract] bool DeleteUser(DTO_TB_USERS oUser); [OperationContract] bool DeleteUserByLamada(ExpressionNode expressionNode); [OperationContract] bool UpdateUser(DTO_TB_USERS oUser); #endregion #region 部門管理 [OperationContract] List<DTO_TB_DEPARTMENT> GetDepartments(ExpressionNode expressionNode); [OperationContract] DTO_TB_DEPARTMENT AddDepartment(DTO_TB_DEPARTMENT oDept); [OperationContract] bool DeleteDepartment(DTO_TB_DEPARTMENT oDept); [OperationContract] bool DeleteDeptByLamada(ExpressionNode expressionNode); [OperationContract] bool UpdateDepartment(DTO_TB_DEPARTMENT oDept); #endregion #region 角色管理 [OperationContract] List<DTO_TB_ROLE> GetRoles(ExpressionNode expressionNode); [OperationContract] DTO_TB_ROLE AddRole(DTO_TB_ROLE oRole); #endregion #region 菜單管理 [OperationContract] List<DTO_TB_MENU> GetMenus(ExpressionNode expressionNode); [OperationContract] DTO_TB_MENU AddMenu(DTO_TB_MENU oMenu); #endregion }
這裏要說明一點,在經過lamada表達式查詢的方法裏面爲何不直接用Expression<Func<DTO_TB_USERS,bool>>這種類型,而要使用ExpressionNode這種類型的變量呢?
這是由於Expression不支持序列化,沒法用於WCF數據的傳遞。ExpressionNode這個對象的使用須要添加Serialize.Linq這個dll的引用,還好有咱們神奇的NuGet,讓咱們不再用去網上找一大堆的dll了。
咱們公用的增刪改查封裝到了BaseService這個父類裏面。
這個父類主要作了兩件事:一是MEF的初始化;二是通用增刪改查的實現。全部dto對象和領域model的映射都在這裏統一管理。
UI層裏面,爲了更好分離代碼,咱們引入了接口編程的機制,引入了ESTM.Web.IBLL和ESTM.Web.BLL兩個項目,如圖:
爲何要有這麼一個接口層?以前C#進階系列——MEF實現設計上的「鬆耦合」(終結篇:面向接口編程)這篇已經作過介紹,對面向接口編程不瞭解的朋友能夠看看。
這個dll主要定義接口規則。
public interface IPowerManager { List<DTO_TB_USERS> GetUsers(Expression<Func<DTO_TB_USERS, bool>> selector = null); DTO_TB_USERS AddUser(DTO_TB_USERS oUser); bool DeleteUser(DTO_TB_USERS oUser); bool UpdateUser(DTO_TB_USERS oUser); bool DeleteUser(Expression<Func<DTO_TB_USERS, bool>> selector = null); List<DTO_TB_DEPARTMENT> GetDepartments(Expression<Func<DTO_TB_DEPARTMENT, bool>> selector = null); DTO_TB_DEPARTMENT AddDepartment(DTO_TB_DEPARTMENT oDept); bool DeleteDepartment(DTO_TB_DEPARTMENT oDept); bool DeleteDepartment(Expression<Func<DTO_TB_DEPARTMENT, bool>> selector = null); bool UpdateDepartment(DTO_TB_DEPARTMENT oDept); List<DTO_TB_ROLE> GetRoles(Expression<Func<DTO_TB_ROLE, bool>> selector = null); List<DTO_TB_MENU> GetMenus(Expression<Func<DTO_TB_MENU, bool>> selector = null); }
這個dll用於實現ESTM.Web.IBLL裏面的接口方法
public class CreatePowerManagerService { private static ServiceReference_PowerManager.PowerManageWCFServiceClient oPowerManagerClient = null; private static object obj = new object(); public static ServiceReference_PowerManager.PowerManageWCFServiceClient GetInstance() { lock (obj) { if (oPowerManagerClient == null) { oPowerManagerClient = new ServiceReference_PowerManager.PowerManageWCFServiceClient(); } } return oPowerManagerClient; } }
因爲是採用的添加服務引用的方式引用的WCF服務,因此在這一層須要添加WCF服務的引用。在實現這部分代碼的時候博主遇到過一個問題,在此和朋友們分享一下。因爲在WCF服務的設計裏面用到了DTO對象,而在ESTM.Web.BLL這個項目裏面也要用到DTO,可是添加WCF服務引用的時候默認的是WCF服務裏面的DTO,而不是ESTM.Common.DtoModel這個項目的DTO對象,這樣就有問題了,每次若是咱們須要改動下dto的內容,那麼咱們就須要更新下服務引用。還好,微軟給咱們選擇的機制,咱們來看圖
這樣就能解決上面的問題了。
按照面向接口的機制,ESTM.Web項目是不須要添加ESTM.Web.BLL這個實現層項目引用的,經過MEF動態導入ESTM.Web.BLL裏面的對象。咱們來看代碼:
View頁面
JS代碼咱們來看一個頁面就行了,其餘頁面相似:
效果圖:
在作頁面數據更新的時候,博主又遇到一個問題:ObjectStateManager 中已存在具備同一鍵的對象。ObjectStateManager 沒法跟蹤具備相同鍵的多個對象。在此仍是記錄下解決方案:
在倉儲的公共實現類中將
public virtual IQueryable<TEntity> Entities { get { return UnitOfWork.context.Set<TEntity>(); } }
改爲
public virtual IQueryable<TEntity> Entities { get { return UnitOfWork.context.Set<TEntity>().AsNoTracking() as IQueryable<TEntity>; } }
就能夠了。
至此,從領域模型到Web前端的代碼基本完成,可能不少代碼並未完善,好比異常處理、數據驗證等。以前寫過一篇CS版本的權限系統 系統設計——權限系統,不少朋友找我要過源碼,那個時候可能代碼都在工做的項目中,沒辦法抽離出來,在此表示抱歉。如今作了一個BS的,感受BS比CS界面好看,在這裏將源碼分享出來,固然這裏的代碼確定也不太全,不少沒實現的功能還須要本身去實現,可是基本的架子搭起來了,有興趣能夠看看。源碼下載