• 领域驱动设计案例之领域层框架搭建


    根据前面对领域驱动设计概念以及一些最佳实践的理解,领域模型是系统最核心的部分,我们还是采用前面销售订单的例子,这个案例系统的核心构建就从领域层开始。领域层框架搭建主要完成两个任务:

    1.领域模型的建立,聚合与聚合根的确定,关系的确定。

    2.建立支持DDD理论的领域层接口。

    这里先上代码图,再详细讲每个部分的主要功能:

    1.Model中主要确定了领域对象,聚合与聚合根,关联关系等,我们这里采用的是EF 的Model First建模,你也可以采取Code First。如下图:

    2.Aggreate中主要定义了两个接口,一个是IEntity,一个是IAggreateRoot,分别表示实体与聚合根。我这里直接用表未来的GUID主键作为实体的唯一标识符

    using System;
    
    namespace Order.Domain.Aggreate
    {
        public interface IEntity
        {
            Guid Id { get; }
        }
    }
    namespace Order.Domain.Aggreate
    {
        public interface IAggreateRoot:IEntity
        {
        }
    }

     3.Repository中主要定义了IRepository与IRepositoryContext接口。

        将IRepository接口定义在领域层的主要目的是:  

       1)领域层不应该直接依赖于仓储实现:如果领域层依赖于仓储实现,一是技术绑定太紧密,二是仓储要对领域对象作操作,会造成循环依赖。

       2)将接口定义在领域层,减少技术架构依赖,应用层或领域层要使用某个仓储实现时,通过依赖注入的方式将仓储实现注射到应用层或领域层,具体IOC在使用时对应用层与领域层的建议见前面的文章。

      定义IRepositoryContext接口的主要目的是:因为我们采用的持久化机制是EF,EF是通过DBContext来管理数据操作的事务,一般是针对单实体的。通常我们的业务需要持久化整个聚合的多个实体或通过领域服务或应用服务持久化多个聚合,多个实体或聚合在业务上需要保持一致性,为了达到这个目的,我们引入了工作单元模式与定义了仓储上下文,通过仓储上下文来管理操作的多个实体或多个聚合中的实体,然后通过工作单元模式统一提交来保证事务,从而保证业务的一致性。

    using System;
    using System.Collections.Generic;
    using System.Linq.Expressions;
    using Order.Domain.Aggreate;
    
    namespace Order.Domain.Repository
    {
        public interface IRepository<TAggreateRoot> where TAggreateRoot:class,IAggreateRoot
        {
            #region 创建对象
            void Create(TAggreateRoot aggreateroot);
            #endregion
            #region 重建对象
            TAggreateRoot GetbyId(Guid id);
            List<TAggreateRoot> GetbyCondition(Expression<Func<TAggreateRoot, bool>> condition);
            #endregion
            #region 更新对象
            void Update(TAggreateRoot aggreateroot);
            #endregion
            #region 销毁对象
            void Remove(TAggreateRoot aggreateroot);
            void RemoveById(Guid id);
            #endregion
        }
    }
    namespace Order.Domain.Repository
    {
        public interface IUnitOfWork
        {
            bool Committed { get; }
            void Commit();
            void RollBack();
        }
    }
    using Order.Domain.Aggreate;
    using System;
    
    namespace Order.Domain.Repository
    {
        public interface IRepositoryContext:IUnitOfWork,IDisposable
        {
            Guid ContextId { get; }
            /// <summary>
            /// 在事务上下文中标记聚合根为创建状态
            /// </summary>
            /// <typeparam name="TAggreateRoot"></typeparam>
            /// <param name="aggreateroot"></param>
            void RegisterCreate<TAggreateRoot>(TAggreateRoot aggreateroot) where TAggreateRoot:class,IAggreateRoot;
            /// <summary>
            /// 在事务上下文中标记聚合根为更改状态
            /// </summary>
            /// <typeparam name="TAggreateRoot"></typeparam>
            /// <param name="aggreateroot"></param>
            void RegisterUpdate<TAggreateRoot>(TAggreateRoot aggreateroot) where TAggreateRoot : class, IAggreateRoot;
            /// <summary>
            /// 在事务上下文中标记聚合根为销毁状态
            /// </summary>
            /// <typeparam name="TAggreateRoot"></typeparam>
            /// <param name="aggreateroot"></param>
            void RegisterRemove<TAggreateRoot>(TAggreateRoot aggreateroot) where TAggreateRoot : class, IAggreateRoot;
         }
    }

     欢迎加入QQ讨论群:309287205

  • 相关阅读:
    关于树论【动态树问题(LCT)】
    caioj1462: 【EXKMP】回文串
    Node.js 文件上传 cli tools
    VuePress & Markdown Slot
    npm config set registry
    Front End Frameworks Trending 2021
    如何使用 VuePress 搭建一个 element-ui 风格的文档网站
    Semantic Pull Requests All In One
    [POJ2559]Largest Rectangle in a Histogram
    [POJ3253]Fence Repair
  • 原文地址:https://www.cnblogs.com/malaoko/p/4997085.html
Copyright © 2020-2023  润新知