DDD领域驱动设计之领域基础设施层

1、DDD领域驱动设计实践篇之如何提取模型

2、DDD领域驱动设计之聚合、实体、值对象

其实这里说的基础设施层只是领域层的一些接口和基类而已,没有其他的如日子工具等代码,仅仅是为了说明领域层的一些基础问题

1、领域事件简单实现代码,都是来至ASP.NET设计模式书中的代码

namespace DDD.Infrastructure.Domain.Events
{
    public interface IDomainEvent
    {
    }
}
namespace DDD.Infrastructure.Domain.Events
{
    public interface IDomainEventHandler<T> : IDomainEventHandler
        where T : IDomainEvent
    {
        void Handle(T e);
    }

    public interface IDomainEventHandler
    {

    }

}
namespace DDD.Infrastructure.Domain.Events
{
    public interface IDomainEventHandlerFactory
    {
        IEnumerable<IDomainEventHandler<T>> GetDomainEventHandlersFor<T>(T domainEvent)
                                                                where T : IDomainEvent;
    }

}
namespace DDD.Infrastructure.Domain.Events
{
    public class StructureMapDomainEventHandlerFactory : IDomainEventHandlerFactory
    {
        public IEnumerable<IDomainEventHandler<T>> GetDomainEventHandlersFor<T>
                                              (T domainEvent) where T : IDomainEvent
        {
            return ObjectFactory.GetAllInstances<IDomainEventHandler<T>>();
        }
    }

}
namespace DDD.Infrastructure.Domain.Events
{
    public static class DomainEvents
    {
        public static IDomainEventHandlerFactory DomainEventHandlerFactory { get; set; }

        public static void Raise<T>(T domainEvent) where T : IDomainEvent
        {
            var handlers = DomainEventHandlerFactory.GetDomainEventHandlersFor(domainEvent);
            foreach (var item in handlers)
            {
                item.Handle(domainEvent);
            }
        }
    }
}

2、领域层接口代码,很多都是来至MS NLayer代码和google code

namespace DDD.Infrastructure.Domain
{
    public interface IEntity<out TId>
    {
        TId Id { get; }
    }
}
namespace DDD.Infrastructure.Domain
{
    public interface IAggregateRoot : IAggregateRoot<string>
    {
    }

    public interface IAggregateRoot<out TId> : IEntity<TId>
    {
    }
}
namespace DDD.Infrastructure.Domain
{
    public abstract class EntityBase : EntityBase<string>
    {
        protected EntityBase()
            :this(null)
        {
        }

        protected EntityBase(string id)
        {
            this.Id = id;
        }

        public override string Id
        {
            get
            {
                return base.Id;
            }
            set
            {
                base.Id = value;
                if (string.IsNullOrEmpty(this.Id))
                {
                    this.Id = EntityBase.NewId();
                }
            }
        }

        public static string NewId()
        {
            return Guid.NewGuid().ToString("N");
        }
    }

    public abstract class EntityBase<TId> : IEntity<TId>
    {
        public virtual TId Id
        {
            get;
            set;
        }

        public virtual IEnumerable<BusinessRule> Validate()
        {
            return new BusinessRule[] { };
        }

        public override bool Equals(object entity)
        {
            return entity != null
               && entity is EntityBase<TId>
               && this == (EntityBase<TId>)entity;
        }

        public override int GetHashCode()
        {
            return this.Id.GetHashCode();
        }

        public static bool operator ==(EntityBase<TId> entity1, EntityBase<TId> entity2)
        {
            if ((object)entity1 == null && (object)entity2 == null)
            {
                return true;
            }

            if ((object)entity1 == null || (object)entity2 == null)
            {
                return false;
            }

            if (entity1.Id.ToString() == entity2.Id.ToString())
            {
                return true;
            }

            return false;
        }

        public static bool operator !=(EntityBase<TId> entity1, EntityBase<TId> entity2)
        {
            return (!(entity1 == entity2));
        }
    }

}
namespace DDD.Infrastructure.Domain
{
    public interface IRepository<TEntity> : IRepository<TEntity, string>
         where TEntity : IAggregateRoot
    {
    }

    public interface IRepository<TEntity, in TId>
        where TEntity : IAggregateRoot<TId>
    {
        void Modify(TEntity entity);
        void Add(TEntity entity);
        void Remove(TId id);

        IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> predicate);
        IQueryable<TEntity> All();
        TEntity Find(TId id);
    }
}
namespace DDD.Infrastructure.Domain
{
    public class BusinessRule
    {
        private string _property;
        private string _rule;

        public BusinessRule(string rule)
        {
            this._rule = rule;
        }

        public BusinessRule(string property, string rule)
        {
            this._property = property;
            this._rule = rule;
        }

        public string Property
        {
            get { return _property; }
            set { _property = value; }
        }

        public string Rule
        {
            get { return _rule; }
            set { _rule = value; }
        }
    }

}
namespace DDD.Infrastructure.Domain
{
    /// <summary>
    /// Abstract Base Class for Value Objects
    /// Based on CodeCamp Server codebase http://code.google.com/p/codecampserver
    /// </summary>
    /// <typeparam name="TObject">The type of the object.</typeparam>
    [Serializable]
    public class ValueObject<TObject> : IEquatable<TObject> where TObject : class
    {

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="left">The left.</param>
        /// <param name="right">The right.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator ==(ValueObject<TObject> left, ValueObject<TObject> right)
        {
            if (ReferenceEquals(left, null))
                return ReferenceEquals(right, null);

            return left.Equals(right);
        }

        /// <summary>
        /// Implements the operator !=.
        /// </summary>
        /// <param name="left">The left.</param>
        /// <param name="right">The right.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator !=(ValueObject<TObject> left, ValueObject<TObject> right)
        {
            return !(left == right);
        }

        /// <summary>
        /// Equalses the specified candidate.
        /// </summary>
        /// <param name="candidate">The candidate.</param>
        /// <returns>
        /// true if the current object is equal to the <paramref name="candidate"/> parameter; otherwise, false.
        /// </returns>
        public override bool Equals(object candidate)
        {
            if (candidate == null)
                return false;

            var other = candidate as TObject;

            return Equals(other);
        }

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
        /// </returns>
        public virtual bool Equals(TObject other)
        {
            if (other == null)
                return false;

            Type t = GetType();

            FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

            foreach (FieldInfo field in fields)
            {
                object otherValue = field.GetValue(other);
                object thisValue = field.GetValue(this);

                //if the value is null...
                if (otherValue == null)
                {
                    if (thisValue != null)
                        return false;
                }
                //if the value is a datetime-related type...
                else if ((typeof(DateTime).IsAssignableFrom(field.FieldType)) ||
                         ((typeof(DateTime?).IsAssignableFrom(field.FieldType))))
                {
                    string dateString1 = ((DateTime)otherValue).ToLongDateString();
                    string dateString2 = ((DateTime)thisValue).ToLongDateString();
                    if (!dateString1.Equals(dateString2))
                    {
                        return false;
                    }
                    continue;
                }
                //if the value is any collection...
                else if (typeof(IEnumerable).IsAssignableFrom(field.FieldType))
                {
                    IEnumerable otherEnumerable = (IEnumerable)otherValue;
                    IEnumerable thisEnumerable = (IEnumerable)thisValue;

                    if (!otherEnumerable.Cast<object>().SequenceEqual(thisEnumerable.Cast<object>()))
                        return false;
                }
                //if we get this far, just compare the two values...
                else if (!otherValue.Equals(thisValue))
                    return false;
            }

            return true;
        }

        /// <summary>
        /// Serves as a hash function for a particular type.
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"/>.
        /// </returns>
        public override int GetHashCode()
        {
            IEnumerable<FieldInfo> fields = GetFields();

            const int startValue = 17;
            const int multiplier = 59;

            int hashCode = startValue;

            foreach (FieldInfo field in fields)
            {
                object value = field.GetValue(this);

                if (value != null)
                    hashCode = hashCode * multiplier + value.GetHashCode();
            }

            return hashCode;
        }

        /// <summary>
        /// Gets the fields.
        /// </summary>
        /// <returns>FieldInfo collection</returns>
        private IEnumerable<FieldInfo> GetFields()
        {
            Type t = GetType();

            var fields = new List<FieldInfo>();

            while (t != typeof(object))
            {
                fields.AddRange(t.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public));

                t = t.BaseType;
            }

            return fields;
        }

    }
}

  

时间: 2024-11-01 18:13:01

DDD领域驱动设计之领域基础设施层的相关文章

DDD领域驱动设计之领域服务

1.DDD领域驱动设计实践篇之如何提取模型 2.DDD领域驱动设计之聚合.实体.值对象 3.DDD领域驱动设计之领域基础设施层 什么是领域服务,DDD书中是说,有些类或者方法,放实体A也不好,放实体B也不好,因为很可能会涉及多个实体或者聚合的交互(也可能是多个相同类型的实体),此时就应该吧这些代码放到领域服务中,领域服务其实就跟传统三层的BLL很相似,只有方法没有属性,也就没有状态,而且最好是用动词命名,service为后缀,但是真正到了实践的时候,很多时候是很难区分是领域实体本身实现还是用领域

领域驱动设计:分离领域

本章大部分内容摘自:<领域驱动设计:软件核心复杂性应对之道>一书中的第四章,分离领域,纯属原创.如有错误请指正,相互学习. 模式:LAYERED ARCHITECTURE (分层结构) 在面向对象的程序中,常常会在业务对象中直接写入用户界面.数据库访问等支持代码.而一些额外的业务逻辑则会被嵌入到用户界面组件和数据库脚本的行为中.这么做是为了以最简单的方式在短期内完成开发工作. 如果与领域有关的代码大量分散在大量的其他代码之中,那么查看和分析领域代码就会变得相当困难.对用户界面的简单修改实际上很

领域驱动设计 ——一种将概念模型化的方式

原文发布于:http://www.gufeng.tech/ 1.引子 2004年Eric Evans 发表了一本书:<Domain-Driven Design: Tackling Complexity in the Heart of Software>(中文名:<领域驱动设计:软件核心复杂性应对之道>),在这本书中作者提出了领域驱动设计(DDD)的概念,到现在已经10多年的时间了. 1.1 面向对象与面向对象语言 面向对象思想已经存在相当长的历史了(相对于软件的历史),我而们使用的

NET 领域驱动设计实战系列总结

NET 领域驱动设计实战系列总结 一.引用 其实在去年本人已经看过很多关于领域驱动设计的书籍了,包括Microsoft .NET企业级应用框架设计.领域驱动设计C# 2008实现.领域驱动设计:软件核心复杂性应对之道.实现领域驱动设计和Asp.net 设计模式等书,但是去年的学习仅仅限制于看书,当时看下来感觉,领域驱动设计并没有那么难,并且感觉有些领域驱动设计的内容并没有好的,反而觉得有点华而不实的感觉,所以去年也就放弃了领域驱动设计系列的分享了,但是到今年,在博客园看到还是有很多人写领域驱动的

[.NET领域驱动设计实战系列]专题十一:.NET 领域驱动设计实战系列总结

一.引用 其实在去年本人已经看过很多关于领域驱动设计的书籍了,包括Microsoft .NET企业级应用框架设计.领域驱动设计C# 2008实现.领域驱动设计:软件核心复杂性应对之道.实现领域驱动设计和Asp.net 设计模式等书,但是去年的学习仅仅限制于看书,当时看下来感觉,领域驱动设计并没有那么难,并且感觉有些领域驱动设计的内容并没有好的,反而觉得有点华而不实的感觉,所以去年也就放弃了领域驱动设计系列的分享了,但是到今年,在博客园看到还是有很多人写领域驱动的文章,以及介绍了领域驱动设计相关的

【系统架构理论】一篇文章搞掂:领域驱动设计

一.什么是领域驱动设计 1.1.面向业务的设计 当我们需要构建一个业务复杂的系统,我们不仅要从技术角度去构建一个稳健的系统,还要从业务角度出发,保证系统能满足业务需求. 架构设计的考虑点:不仅面向技术,更应该面向业务:面对不同的业务复杂度,选择的架构可能不同. 架构师的工作:面对复杂的业务逻辑,需要整合业务和技术才能很好地解决.业务架构驱动技术架构. 一个典型开发团队:新手.中级开发者.高级开发者/架构师(技术架构).领域专家/产品经理(业务架构).项目经理 要解决的问题:将复杂的业务架构梳理好

领域驱动设计(1)认识了解什么是领域驱动

领域驱动(1)认识了解什么是领域驱动 废话 领域驱动设计已经出现很早了,说实话很早以前的我很不喜欢看书.不论是pdf还是书本.买过的书籍还是有几本的,这仅有的几本书还是因为公司的业务或者某项技术遇到瓶颈需要自己和团队进行突破的时候用来填充自己的大脑用的,当然这是被动的,毕竟:生下来.活下去很重要的.这两年微服务的出现好像又推动了领域驱动设计的发展. 一.解释什么是领域驱动: 其实对于IT的行业的我们理解起来很容易,很有可能在日常生活工作中我们也都有过接触,对于领域是一个什么样的概念 举例: 比如

【DDD】领域驱动设计实践 —— Application层实现

本文是DDD框架实现讲解的第二篇,主要介绍了DDD的Application层的实现,详细讲解了service.assemble的职责和实现.文末附有github地址.相比于<领域驱动设计>原书中的航运系统例子,社交服务系统的业务场景对于大家更加熟悉,相信更好理解.本文是[DDD]系列文章的其中一篇,其他可参考:使用领域驱动设计思想实现业务系统 Application层 在DDD设计思想中,Application层主要职责为组装domain层各个组件及基础设施层的公共组件,完成具体的业务服务.A

DDD领域驱动设计基本理论知识总结

领域驱动设计之领域模型 加一个导航,关于如何设计聚合的详细思考,见这篇文章. 2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity in the Heart of Software (领域驱动设计),简称Evans DDD.领域驱动设计分为两个阶段: 以一种领域专家.设计人员.开发人员都能理解的通用语言作为相互交流的工具,在交流的过程中发现领域概念,然后将这些概念设计成一个领域模型:由领域模型驱动软件设计,用代码来实现该领域模型: