zoukankan      html  css  js  c++  java
  • DDD领域驱动设计初探(七):Web层的搭建

    前言:好久没更新博客了,每天被该死的业务缠身,今天正好一个模块完成了,继续来完善我们的代码。之前的六篇完成了领域层、应用层、以及基础结构层的部分代码,这篇打算搭建下UI层的代码。

    DDD领域驱动设计初探系列文章:

    一、UI层介绍

    在DDD里面,UI层的设计也分为BS和CS,本篇还是以Web为例来说明。我们的Web采用的是MVC+bootstrap的架构。Table组件使用的是bootstrap table,之所以用它是因为它的API比较全,并且博主觉得它的风格适用于各种类型的设备,无论是PC端还是手机端都都能很好的兼容各种浏览器。

    这里还是贴出bootstrap API的相关地址。

    Bootstrap中文网:http://www.bootcss.com/       

    Bootstrap Table Demo:http://issues.wenzhixin.net.cn/bootstrap-table/index.html

    Bootstrap Table API:http://bootstrap-table.wenzhixin.net.cn/zh-cn/documentation/

    Bootstrap Table源码:https://github.com/wenzhixin/bootstrap-table

    Bootstrap DataPicker:http://www.bootcss.com/p/bootstrap-datetimepicker/

    Bootstrap离线API

    二、代码示例

    上篇完成了WCF的设计代码,但是具体的业务逻辑的代码还没有,我们先来实现具体业务的CURD代码。

    1、WCF代码

    1.1 WCF服务业务接口代码

    复制代码
        /// <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
        }
    复制代码

    1.2 WCF接口实现代码:

     PowerManageWCFService

    这里要说明一点,在通过lamada表达式查询的方法里面为什么不直接用Expression<Func<DTO_TB_USERS,bool>>这种类型,而要使用ExpressionNode这种类型的变量呢?

    这是因为Expression不支持序列化,无法用于WCF数据的传递。ExpressionNode这个对象的使用需要添加Serialize.Linq这个dll的引用,还好有我们神奇的NuGet,让我们再也不用去网上找一大堆的dll了。

    我们公用的增删改查封装到了BaseService这个父类里面。

    1.3 BaseService代码

     BaseService

    这个父类主要做了两件事:一是MEF的初始化;二是通用增删改查的实现。所有dto对象和领域model的映射都在这里统一管理。

    2、UI层代码

    UI层里面,为了更好分离代码,我们引入了接口编程的机制,引入了ESTM.Web.IBLL和ESTM.Web.BLL两个项目,如图:

    为什么要有这么一个接口层?之前C#进阶系列——MEF实现设计上的“松耦合”(终结篇:面向接口编程)这篇已经做过介绍,对面向接口编程不了解的朋友可以看看。

    2.1 ESTM.Web.IBLL代码

    这个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);
    
        }
    复制代码

    2.2 ESTM.Web.BLL代码

    这个dll用于实现ESTM.Web.IBLL里面的接口方法

     PowerManager : IPowerManager
    复制代码
      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的内容,那么我们就需要更新下服务引用。还好,微软给我们选择的机制,我们来看图

    这样就能解决上面的问题了。

    2.3 ESTM.Web代码

    按照面向接口的机制,ESTM.Web项目是不需要添加ESTM.Web.BLL这个实现层项目引用的,通过MEF动态导入ESTM.Web.BLL里面的对象。我们来看代码:

     PowerManagerController

    View页面

     _Layout.cshtml
     Department.cshtml

    JS代码我们来看一个页面就好了,其他页面类似:

     DepartmentManage.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界面好看,在这里将源码分享出来,当然这里的代码肯定也不太全,很多没实现的功能还需要自己去实现,但是基本的架子搭起来了,有兴趣可以看看。源码下载

  • 相关阅读:
    JqGrid常用示例
    jqGrid无刷新分页,添加行按钮
    C#两个实体之间相同属性的映射
    Log4Net日志记录
    C#压缩图片
    ASP.Net MVC4.0+无刷新分页
    世界各个国家中英文sql建表
    ASP.NET多语言
    分布式事务处理中的幂等性
    分布式事务前瞻-接口幂等性
  • 原文地址:https://www.cnblogs.com/Justsoso-WYH/p/10836523.html
Copyright © 2011-2022 走看看