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;
        }

    }
}

  

posted @ 2014-08-26 21:18  lawbc  阅读(4413)  评论(0编辑  收藏