设为首页 加入收藏

TOP

应用程序框架(一):DDD分层架构:领域实体(基础篇)(二)
2019-09-17 18:53:40 】 浏览:89
Tags:应用程序 框架 DDD 分层 架构 领域 实体 基础
/// <param name="id">标识</param> protected EntityBase( Guid id ) { Id = id; } /// <summary> /// 标识 /// </summary> public Guid Id { get; private set; } } }

   它们的唯一变化是Id数据类型不同,我们可以把Id类型设为object,从而支持所有类型。

namespace Util.Domains { /// <summary>
    /// 领域实体 /// </summary>
    public abstract class EntityBase{ /// <summary>
        /// 初始化领域实体 /// </summary>
        /// <param name="id">标识</param>
        protected EntityBase( object id ) { Id = id; } /// <summary>
        /// 标识 /// </summary>
        public object Id { get; private set; } } }

   但弱类型的object将导致装箱和拆箱,另外也不太易用,这时候是泛型准备登场的时候了。

namespace Util.Domains { /// <summary>
    /// 领域实体 /// </summary>
    /// <typeparam name="TKey">标识类型</typeparam>
    public abstract class EntityBase<TKey> { /// <summary>
        /// 初始化领域实体 /// </summary>
        /// <param name="id">标识</param>
        protected EntityBase( TKey id ) { Id = id; } /// <summary>
        /// 标识 /// </summary>
 [Required] public TKey Id { get; private set; } } }

   将标识类型通过泛型参数TKey传进来,由于标识类型可以任意,所以不需要进行泛型约束。另外在Id上方加了一个Required特性,当Id为字符串或其它引用类型的时候,就能派上用场了。

  下面要解决的问题是实体对象相等性比较,需要重写Equals,GetHashCode方法,另外需要重写==和!=两个操作符重载。

/// <summary>
/// 相等运算
/// </summary>
public override bool Equals( object entity ) 
{
    if ( entity == null )
       return false;
    if ( !( entity is EntityBase<TKey> ) )
       return false;
    return this == (EntityBase<TKey>)entity;
}

/// <summary>
/// 获取哈希
/// </summary>
public override int GetHashCode() 
{
     return Id.GetHashCode();
}

/// <summary>
/// 相等比较
/// </summary>
/// <param name="entity1">领域实体1</param>
/// <param name="entity2">领域实体2</param>
public static bool operator ==( EntityBase<TKey> entity1, EntityBase<TKey> entity2 ) 
{
    if ( (object)entity1 == null && (object)entity2 == null )
        return true;
    if ( (object)entity1 == null || (object)entity2 == null )
        return false;
    if ( entity1.Id == null )
        return false;
    if ( entity1.Id.Equals( default( TKey ) ) )
        return false;
    return entity1.Id.Equals( entity2.Id );
}

/// <summary>
/// 不相等比较
/// </summary>
/// <param name="entity1">领域实体1</param>
/// <param name="entity2">领域实体2</param>
public static bool operator !=( EntityBase<TKey> entity1, EntityBase<TKey> entity2 ) 
{
    return !( entity1 == entity2 );
}

  在操作符==的代码中,有一句需要注意,entity1.Id.Equals( default( TKey ) ),比如,一个实体的标识为int类型,这个实体在刚创建的时候,Id默认为0,另外创建一个该类的实例,Id也为0,那么这两个实体是相等还是不等?从逻辑上它们是不相等的,属于不同的实体, 只是标识目前还没有创建,可能需要等到保存到数据库中才能产生。这有什么影响呢?当进行某些集合操作时,如果你发现操作N个实体,但只有一个实体操作成功,那很有可能是因为这些实体的标识是默认值,而你的相等比较没有识别出来,这一句代码能够解决这个问题。

  考虑领域实体基类还能帮我们干点什么,其实还很多,比如状态输出、初始化、验证、日志等。下面先来介绍一下状态输出。

  当我在操作每个实体的时候,我经常需要在日志中记录完整的实体状态,即实体所有属性名值对的列表。这样方便我在查找问题的时候,可以了解某个实体当时是个什么情况。

  要输出实体的状态,最方便的方法是重写ToString,然后把实体状态列表返回回来。这样ToString方法将变得有意义,因为它输出一个实体的类名基本没什么用。

  要输出实体的全部属性值,一个办法是通过反射在基类中进行,但这可能会造成一点性能下降,由于通过代码生成器可以轻松生成这个操作,所以我没有采用反射的方法。

/// <summary>
/// 描述
/// </summary>
private StringBuilder _description;

/// <summary>
/// 输出领域对象的状态
首页 上一页 1 2 3 4 5 下一页 尾页 2/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇战狼:业务高速增长下,如何保证.. 下一篇互联网分层架构的本质

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目