Browse Source

Translate object extensions document

pull/3548/head
liangshiwei 6 years ago
parent
commit
66595e35f5
  1. 3
      docs/zh-Hans/AutoMapper-Integration.md
  2. 18
      docs/zh-Hans/Best-Practices/Application-Services.md
  3. 1
      docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md
  4. 267
      docs/zh-Hans/Object-Extensions.md
  5. 17
      docs/zh-Hans/Object-To-Object-Mapping.md
  6. 4
      docs/zh-Hans/docs-nav.json

3
docs/zh-Hans/AutoMapper-Integration.md

@ -1,3 +0,0 @@
## AutoMapper Integration
TODO

18
docs/zh-Hans/Best-Practices/Application-Services.md

@ -17,7 +17,7 @@
##### 基础DTO
**推荐** 为实体定义一个**基础**DTO.
**推荐** 为聚合根定义一个**基础**DTO.
- 直接包含实体中所有的**原始属性**.
- 例外: 出于**安全**原因,可以**排除**某些属性(像 `User.Password`).
@ -27,7 +27,7 @@
```c#
[Serializable]
public class IssueDto : FullAuditedEntityDto<Guid>
public class IssueDto : ExtensibleFullAuditedEntityDto<Guid>
{
public string Title { get; set; }
public string Text { get; set; }
@ -57,7 +57,7 @@ public class IssueLabelDto
````C#
[Serializable]
public class IssueWithDetailsDto : FullAuditedEntityDto<Guid>
public class IssueWithDetailsDto : ExtensibleFullAuditedEntityDto<Guid>
{
public string Title { get; set; }
public string Text { get; set; }
@ -66,14 +66,14 @@ public class IssueWithDetailsDto : FullAuditedEntityDto<Guid>
}
[Serializable]
public class MilestoneDto : EntityDto<Guid>
public class MilestoneDto : ExtensibleEntityDto<Guid>
{
public string Name { get; set; }
public bool IsClosed { get; set; }
}
[Serializable]
public class LabelDto : EntityDto<Guid>
public class LabelDto : ExtensibleEntityDto<Guid>
{
public string Name { get; set; }
public string Color { get; set; }
@ -120,6 +120,7 @@ Task<List<QuestionWithDetailsDto>> GetListAsync(QuestionListQueryDto queryDto);
* **推荐** 使用 `CreateAsync` 做为**方法名**.
* **推荐** 使用**专门的输入DTO**来创建实体.
* **推荐** DTO类从 `ExtensibleObject` 类继承(或任何实现 `ExtensibleObject`的类) 以允许在需要时传递额外的属性.
* **推荐** 使用 **data annotations** 进行输入验证.
* 尽可能在**领域**之间共享常量(通过**domain shared** package定义的常量).
* **推荐** 只需要创建实体的**最少**信息, 但是提供了其他可选属性.
@ -134,7 +135,7 @@ Task<QuestionWithDetailsDto> CreateAsync(CreateQuestionDto questionDto);
````C#
[Serializable]
public class CreateQuestionDto
public class CreateQuestionDto : ExtensibleObject
{
[Required]
[StringLength(QuestionConsts.MaxTitleLength, MinimumLength = QuestionConsts.MinTitleLength)]
@ -151,6 +152,7 @@ public class CreateQuestionDto
- **推荐** 使用 `UpdateAsync` 做为**方法名**.
- **推荐** 使用**专门的输入DTO**来更新实体.
- **推荐** DTO类从 `ExtensibleObject` 类继承(或任何实现 `ExtensibleObject`的类) 以允许在需要时传递额外的属性.
- **推荐** 获取实体的id做为分离的原始参数. 不要包含更新DTO.
- **推荐** 使用 **data annotations** 进行输入验证.
- 尽可能在**领域**之间共享常量(通过**domain shared** package定义的常量).
@ -199,6 +201,10 @@ Task<int> VoteAsync(Guid id, VoteType type);
* **不推荐** 在应用程序服务方法中使用linq/sql查询来自数据库的数据. 让仓储负责从数据源执行linq/sql查询.
#### 额外的属性
* **推荐** 使用 `MapExtraPropertiesTo` 扩展方法 ([参阅](Object-Extensions.md)) 或配置对象映射 (`MapExtraProperties`) 以允许应用开发人员能够扩展对象和服务.
#### 操作/删除 实体
* **推荐** 总是从数据库中获取所有的相关实体以对他们执行操作.

1
docs/zh-Hans/Best-Practices/Data-Transfer-Objects.md

@ -2,6 +2,7 @@
* **推荐****application.contracts** 层中定义DTO.
* **推荐** 在可能和必要的情况下从预构建的 **基础DTO类** 继承 (如 `EntityDto<TKey>`, `CreationAuditedEntityDto<TKey>`, `AuditedEntityDto<TKey>`, `FullAuditedEntityDto<TKey>` 等).
* **推荐** 从**聚合根**的**扩展DTO**继承(如 `ExtensibleAuditedEntityDto<TKey>`), 因为聚合根是可扩展的额外的属性使用这种方式映射到DTO.
* **推荐** 定义 **public getter 和 setter** 的DTO成员 .
* **推荐** 使用 **data annotations** **验证** service输入DTO的属性.
* **不推荐** 在DTO中添加任何 **逻辑**, 在必要的时候可以实现 `IValidatableObject` 接口.

267
docs/zh-Hans/Object-Extensions.md

@ -0,0 +1,267 @@
# 对象扩展
ABP框架提供了 **实体扩展系统** 允许你 **添加额外属性** 到已存在的对象 **无需修改相关类**. 它允许你扩展[应用程序依赖模块](Modules/Index.md)实现的功能,尤其是当你要扩展[模块定义的实体](Customizing-Application-Modules-Extending-Entities.md)和[DTO](Customizing-Application-Modules-Overriding-Services.md)时.
> 你自己的对象通常不需要对象扩展系统,因为你可以轻松的添加常规属性到你的类中.
## IHasExtraProperties 接口
这是一个使类可扩展的接口. 它定义了 `Dictionary` 属性:
````csharp
Dictionary<string, object> ExtraProperties { get; }
````
然后你可以使用此字典添加或获取其他属性.
### 基类
默认以下基类实现了 `IHasExtraProperties` 接口:
* 由 `AggregateRoot` 类实现 (参阅 [entities](Entities.md)).
* 由 `ExtensibleEntityDto`, `ExtensibleAuditedEntityDto`... [DTO](Data-Transfer-Objects.md)基类实现.
* 由 `ExtensibleObject` 实现, 它是一个简单的基类,任何类型的对象都可以继承.
如果你的类从这些类继承,那么你的类也是可扩展的,如果没有,你也可以随时手动继承.
### 基本扩展方法
虽然可以直接使用类的 `ExtraProperties` 属性,但建议使用以下扩展方法使用额外属性.
#### SetProperty
用于设置额外属性值:
````csharp
user.SetProperty("Title", "My Title");
user.SetProperty("IsSuperUser", true);
````
`SetProperty` 返回相同的对象, 你可以使用链式编程:
````csharp
user.SetProperty("Title", "My Title")
.SetProperty("IsSuperUser", true);
````
#### GetProperty
用于读取额外属性的值:
````csharp
var title = user.GetProperty<string>("Title");
if (user.GetProperty<bool>("IsSuperUser"))
{
//...
}
````
* `GetProperty` 是一个泛型方法,对象类型做为泛型参数.
* 如果未设置给定的属性,则返回默认值 (`int` 的默认值为 `0` , `bool` 的默认值是 `false` ... 等).
##### 非基本属性类型
如果您的属性类型不是原始类型(int,bool,枚举,字符串等),你需要使用 `GetProperty` 的非泛型版本,它会返回 `object`.
#### HasProperty
用于检查对象之前是否设置了属性.
#### RemoveProperty
用于从对象中删除属性. 使用此方法代替为属性设置 `null` 值.
### 一些最佳实践
为属性名称使用魔术字符串很危险,因为你很容易输入错误的属性名称-这并不安全;
* 为你的额外属性名称定义一个常量.
* 使用扩展方法轻松设置你的属性.
示例:
````csharp
public static class IdentityUserExtensions
{
private const string TitlePropertyName = "Title";
public static void SetTitle(this IdentityUser user, string title)
{
user.SetProperty(TitlePropertyName, title);
}
public static string GetTitle(this IdentityUser user)
{
return user.GetProperty<string>(TitlePropertyName);
}
}
````
然后, 你可以很容易地设置或获取 `Title` 属性:
````csharp
user.SetTitle("My Title");
var title = user.GetTitle();
````
## Object Extension Manager
你可以为可扩展对象(实现 `IHasExtraProperties`接口)设置任意属性, `ObjectExtensionManager` 用于显式定义可扩展类的其他属性.
显式定义额外的属性有一些用例:
* 允许控制如何在对象到对象的映射上处理额外的属性 (参阅下面的部分).
* 允许定义属性的元数据. 例如你可以在使用[EF Core](Entity-Framework-Core.md)时将额外的属性映射到数据库中的表字段.
> `ObjectExtensionManager` 实现单例模式 (`ObjectExtensionManager.Instance`) ,你应该在应用程序启动之前定义对象扩展. [应用程序启动模板](Startup-Templates/Application.md) 有一些预定义的静态类,可以安全在内部定义对象扩展.
### AddOrUpdate
`AddOrUpdate` 是定义对象额外属性或更新对象额外属性的主要方法.
示例: 为 `IdentityUser` 实体定义额外属性:
````csharp
ObjectExtensionManager.Instance
.AddOrUpdate<IdentityUser>(options =>
{
options.AddOrUpdateProperty<string>("SocialSecurityNumber");
options.AddOrUpdateProperty<bool>("IsSuperUser");
}
);
````
### AddOrUpdateProperty
虽然可以如上所示使用 `AddOrUpdateProperty`, 但如果要定义单个额外的属性,也可以使用快捷的扩展方法:
````csharp
ObjectExtensionManager.Instance
.AddOrUpdateProperty<IdentityUser, string>("SocialSecurityNumber");
````
有时将单个额外属性定义为多种类型是可行的. 你可以使用以下代码,而不是一个一个地定义:
````csharp
ObjectExtensionManager.Instance
.AddOrUpdateProperty<string>(
new[]
{
typeof(IdentityUserDto),
typeof(IdentityUserCreateDto),
typeof(IdentityUserUpdateDto)
},
"SocialSecurityNumber"
);
````
#### 属性配置
`AddOrUpdateProperty` 还可以为属性定义执行其他配置的操作.
Example:
````csharp
ObjectExtensionManager.Instance
.AddOrUpdateProperty<IdentityUser, string>(
"SocialSecurityNumber",
options =>
{
options.CheckPairDefinitionOnMapping = false;
});
````
> 参阅 "对象到对象映射" 部分了解 `CheckPairDefinitionOnMapping` 选项.
`options` 有一个名为 `Configuration` 的字典,该字典存储对象扩展定义甚至可以扩展. EF Core使用它来将其他属性映射到数据库中的表字段. 请参阅[扩展实体文档](Customizing-Application-Modules-Extending-Entities.md).
## 对象到对象映射
假设你已向可扩展的实体对象添加了额外的属性并使用了自动[对象到对象的映射](Object-To-Object-Mapping.md)将该实体映射到可扩展的DTO类. 在这种情况下你需要格外小心,因为额外属性可能包含**敏感数据**,这些数据对于客户端不可用.
本节提供了一些**好的做法**,可以控制对象映射的额外属性。
### MapExtraPropertiesTo
`MapExtraPropertiesTo` 是ABP框架提供的扩展方法,用于以受控方式将额外的属性从一个对象复制到另一个对象. 示例:
````csharp
identityUser.MapExtraPropertiesTo(identityUserDto);
````
`MapExtraPropertiesTo` 需要在**两侧**(本例中是`IdentityUser` 和 `IdentityUserDto`)**定义属性**. 以将值复制到目标对象. 否则即使源对象(在此示例中为 `identityUser` )中确实存在该值,它也不会复制. 有一些重载此限制的方法.
#### MappingPropertyDefinitionChecks
`MapExtraPropertiesTo` 获取一个附加参数来控制单个映射操作的定义检查:
````csharp
identityUser.MapExtraPropertiesTo(
identityUserDto,
MappingPropertyDefinitionChecks.None
);
````
> 要小心,因为 `MappingPropertyDefinitionChecks.None` 会复制所有的额外属性而不进行任何检查. `MappingPropertyDefinitionChecks` 枚举还有其他成员.
如果要完全禁用属性的定义检查,可以在定义额外的属性(或更新现有定义)时进行,如下所示:
````csharp
ObjectExtensionManager.Instance
.AddOrUpdateProperty<IdentityUser, string>(
"SocialSecurityNumber",
options =>
{
options.CheckPairDefinitionOnMapping = false;
});
````
#### 忽略属性
你可能要在映射操作忽略某些属性:
````csharp
identityUser.MapExtraPropertiesTo(
identityUserDto,
ignoredProperties: new[] {"MySensitiveProp"}
);
````
忽略的属性不会复制到目标对象.
#### AutoMapper集成
如果您使用的是[AutoMapper](https://automapper.org/)库,ABP框架还提供了一种扩展方法来利用上面定义的 `MapExtraPropertiesTo` 方法.
你可以在映射配置文件中使用 `MapExtraProperties()` 方法.
````csharp
public class MyProfile : Profile
{
public MyProfile()
{
CreateMap<IdentityUser, IdentityUserDto>()
.MapExtraProperties();
}
}
````
它与 `MapExtraPropertiesTo()` 方法具有相同的参数。
## Entity Framework Core 数据库映射
如果你使用的是EF Core,可以将额外的属性映射到数据库中的表字段. 例:
````csharp
ObjectExtensionManager.Instance
.AddOrUpdateProperty<IdentityUser, string>(
"SocialSecurityNumber",
options =>
{
options.MapEfCore(b => b.HasMaxLength(32));
}
);
````
参阅 [Entity Framework Core 集成文档](Entity-Framework-Core.md) 了解更多内容.

17
docs/zh-Hans/Object-To-Object-Mapping.md

@ -145,6 +145,23 @@ options.AddProfile<MyProfile>(validate: true);
> 如果你有多个配置文件,并且只需要为其中几个启用验证,那么首先使用`AddMaps`而不进行验证,然后为你想要验证的每个配置文件使用`AddProfile`.
### 映射对象扩展
[对象扩展系统](Object-Extensions.md) 允许为已存在的类定义额外属性. ABP 框架提供了一个映射定义扩展可以正确的映射两个对象的额外属性.
````csharp
public class MyProfile : Profile
{
public MyProfile()
{
CreateMap<User, UserDto>()
.MapExtraProperties();
}
}
````
如果两个类都是可扩展对象(实现了 `IHasExtraProperties` 接口),建议使用 `MapExtraProperties` 方法. 更多信息请参阅[对象扩展文档](Object-Extensions.md).
## 高级主题
### IObjectMapper<TContext> 接口

4
docs/zh-Hans/docs-nav.json

@ -140,6 +140,10 @@
{
"text": "设置管理",
"path": "Settings.md"
},
{
"text": "对象扩展",
"path": "Object-Extensions.md"
}
]
},

Loading…
Cancel
Save