ABP官方文档翻译 3.2 值对象

值对象

介绍

  "展现领域描述性层面且没有概念性身份的对象称之为值对象。"(Eric Evans)。

  和实体相反,实体有身份标示(Id),值对象没有身份标示。如果两个实体的身份标示是不同的,那么就认为他们是不同的对象/实体,即使他们的所有属性都是一样的。考虑两个不同的人有相同的名字、姓氏和年龄,但是他们是不同的人,如果他们的身份编号不同的话。但是,对于一个地址(经典的值对象)类,如果两个地址有相同的国家、城市、街道编号等等,则认为为相同的地址。

  在DDD中,值对象是领域对象的另一种类型,可以包含业务逻辑,是领域的重要组成部分。

值对象基类

  ABP有一个ValueObject<T>基类,可以被继承用来轻松创建值对象类型。Address值对象类型示例如下:

public class Address : ValueObject<Address>
{
    public Guid CityId { get; private set; } //A reference to a City entity.

    public string Street { get; private set; }

    public int Number { get; private set; }

    public Address(Guid cityId, string street, int number)
    {
        CityId = cityId;
        Street = street;
        Number = number;
    }
}

  值对象基类重写了等于操作符(还有其他相关的操作符和方法)来比较两个值对象,如果两个值对象所有的属性都相等则认为他们是相等的。所以,所有下面的测试都是通过的:

var address1 = new Address(new Guid("21C67A65-ED5A-4512-AA29-66308FAAB5AF"), "Baris Manco Street", 42);
var address2 = new Address(new Guid("21C67A65-ED5A-4512-AA29-66308FAAB5AF"), "Baris Manco Street", 42);

Assert.Equal(address1, address2);
Assert.Equal(address1.GetHashCode(), address2.GetHashCode());
Assert.True(address1 == address2);
Assert.False(address1 != address2);

  即使在内存中是不同的对象,在我们的领域中也认为他们是完全相同的。

最佳实践

  一些值对象的最佳实践:

  • 将值对象设计为不可变的(如上面的Address类),如果没有好的理由将它设计为可变的话。
  • 组成值对象的属性应形成一个概念上的整体。例如,CityId、Street和编号不应该是一个Person实体分离的属性。这也使得Person实体更简单。

返回主目录

时间: 2024-10-04 21:12:02

ABP官方文档翻译 3.2 值对象的相关文章

ABP官方文档翻译 3.4 领域服务

领域服务 介绍 IDomainService接口和DomainService类 示例 创建接口 服务实现 使用应用服务 一些探讨 为什么只有应用服务? 如何强制使用领域服务? 介绍 领域服务(或者在DDD中单纯的服务)用来执行领域操作和业务规则.Eric Evans在他的DDD书中描述了一个好的服务有三个特征: 1. 与领域概念关联的操作,但不是实体或值对象的自然组成部分. 2. 接口的定义依照领域模型的其他元素. 3. 操作是无状态的. 不像应用服务那样获取或返回DTO,领域服务获取或返回领域

ABP官方文档翻译 4.3 校验数据传输对象

校验数据传输对象 校验简介 使用数据标注 自定义校验 禁用校验 标准化 校验简介 应用的输入首先应该被校验.输入可以是用户的也可以是其他应用的.在一个web应用中,校验通常实现两次:客户端和服务端.客户端校验是为了用户体验.最好现在客户端校验表单并显示给用户无效的字段.但是,服务端校验要更紧要且不可避免的. 服务端校验一般在应用服务或控制器实现(通常,所有的服务从展示层获得数据).应用服务方法应该先检查(校验)输入再使用.ABP提供了良好的基础设施来自动校验应用的输入: 所有的应用服务方法 所有

ABP官方文档翻译 3.3 仓储

 仓储 默认仓储 自定义仓储 自定义仓储接口 自定义仓储实现 基础仓储方法管理数据库连接 查询 获取单个实体 获取实体列表 关于IQueryable 自定义返回值 插入 更新 删除 其他 关于异步方法 管理数据库连接 仓储生命周期 仓储最佳实践 协调领域和数据映射层,使用类集合接口访问领域对象."(Martin Fowler) 实际上,仓储用来执行领域对象的数据库操作(实体和值类型).通常,每个对象(或聚合根)使用单独的仓储. 默认仓储 在ABP中,仓储类实现IRepository<TEn

ABP官方文档翻译 10.1 ABP Nuget包

ABP Nuget包 Packages Abp Abp.AspNetCore Abp.Web.Common Abp.Web Abp.Web.Mvc Abp.Web.Api Abp.Web.Api.OData Abp.Web.Resources Abp.Web.SignalR Abp.Owin Abp.EntityFramework.Common Abp.EntityFramework Abp.EntityFramework.GraphDiff Abp.EntityFrameworkCore Ab

ABP官方文档翻译 6.2.1 ASP.NET Core集成

ASP.NET Core 介绍 迁移到ASP.NET Core? 启动模板 配置 启动类 模块配置 控制器 应用服务作为控制器 过滤器 授权过滤器 审计Action过滤器 校验过滤器 工作单元Action过滤器 异常过滤器 结果过滤器 Ajax请求的结果缓存 模型绑定器 视图 客户端代理 集成测试 介绍 本文档描述了ABP如何集成ASP.NET Core.ASP.NET Core通过Abp.AspNetCore nuget包实现集成. 迁移到ASP.NET Core? 如果你已经有一个工程并考虑

ABP官方文档翻译 5.2 动态We API层

动态Web APID层 创建动态Web API控制器 ForAll方法 重写ForAll ForMethods Http动词 WithVerb方法 HTTP特性 命名约定 API管理器 RemoteServie特性 动态Javascript代理 AJAX参数 单一服务脚本 Anaular集成 启用/禁用 包装结果 关于参数绑定 FormUrl和FormBody特性 DTOs对比原始类型 创建动态Web API控制器 这个文档是针对ASP.NET Web API的.如果你对ASP.NET Core

ABP官方文档翻译 3.8 数据过滤器

数据顾虑器 介绍 预定义过滤器 ISoftDelete 何时使用? IMustHaveTenant 何时使用? IMayHaveTenant 何时使用 禁用过滤器 关于using语句 关于多租户 全局禁用过滤器 启用过滤器 设置过滤器参数 SetTenantId方法 ORM集成 Entity Framework EntityFramework.DynaamicFilters文档 其他ORMs 介绍 软删除模式是常用的模式,这种模式并没有从数据库中删除实体而是打上'deleted'的标记.所以,如

ABP官方文档翻译 6.4 导航

导航 创建菜单 注册导航提供者 显示菜单 每一个网络应用都会有一些菜单用来在pages/screens之间导航.ABP提供了通用的基础设施来创建并显示菜单. 创建菜单 应用可以由不同的模块组成,每一个模块都有自己的菜单项.为了定义菜单项,我们需要创建一个继承自NavigationProvider的类. 假定,我们有一个如下所示的主菜单: Tasks Reports Administration User management Role management 这里,Administration菜单

ABP官方文档翻译 9.3 NHibernate集成

NHibernate集成 Nuget包 配置 实体映射 仓储 默认实现 自定义仓储 应用程序特定基础仓储类 ABP可以使用任何ORM框架,它内置集成NHibernate.此文档将讲解ABP如何使用NHibernate,假定你对NHibernate已经有了一定的了解. Nuget包 在ABP中实现NHibernate做为ORM框架的Nuget包为Abp.NHibernate.你需要在应用程序中添加它.最好在一个单独的程序集中实现NHibernate并在这个程序集里依赖Abp.NHibernate包