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