Skip to content

Commit

Permalink
自定义映射和命名约定文档翻译
Browse files Browse the repository at this point in the history
  • Loading branch information
yihango committed Jun 11, 2021
1 parent 51e2af6 commit 825fcf8
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 55 deletions.
62 changes: 36 additions & 26 deletions cn/Custom-mapping.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Custom mapping
# 自定义映射

### Custom member mapping
### 自定义成员的映射关系

You can customize how Mapster maps values to a property.
Mapster 支持自定义映射某个属性的值:

```csharp
TypeAdapterConfig<TSource, TDestination>
Expand All @@ -11,19 +11,24 @@ TypeAdapterConfig<TSource, TDestination>
src => string.Format("{0} {1}", src.FirstName, src.LastName));
```

You can even map when source and destination property types are different.


也可以在源属性类型和目标属性类型不同时进行映射:

```csharp
TypeAdapterConfig<TSource, TDestination>
.NewConfig()
.Map(dest => dest.Gender, //Genders.Male or Genders.Female
src => src.GenderString); //"Male" or "Female"
.Map(dest => dest.Gender, // dest.Gender: Genders.Male Genders.Female 枚举类型
src => src.GenderString); // src.GenderString: "Male" "Female" 字符串类型
```

### Mapping with condition
### 有条件的映射

可以通过设置 `Map` 方法的第三个参数,实现在 源对象 满足某些条件下进行映射;

当存在多个条件的情况下,Mapster 会依次往下执行判断条件是否满足,直到满足条件为止;

The Map configuration can accept a third parameter that provides a condition based on the source.
If the condition is not met, Mapster will retry with next conditions. Default condition should be added at the end without specifying condition. If you do not specify default condition, null or default value will be assigned.
当找不到满足条件的映射时,将分配空值或默认值:

```csharp
TypeAdapterConfig<TSource, TDestination>
Expand All @@ -33,71 +38,76 @@ TypeAdapterConfig<TSource, TDestination>
.Map(dest => dest.FullName, src => "Mr. " + src.FullName);
```

NOTE: if you would like to skip mapping, when condition is met, you can use `IgnoreIf` (https://github.com/MapsterMapper/Mapster/wiki/Ignoring-members#ignore-conditionally).
> 注意!如果想要在满足条件时跳过映射,应该使用 `IgnoreIf`,详情可参阅 [忽略成员](Ignoring-members.md#ignore-conditionally)
### Mapping to non-public members
### 映射非公开成员

`Map` command can map to private member by specify name of the members.
如果存在私有成员需要映射,那么可以使用 `Map` 方法指定成员名称实现私有成员映射:

```csharp
TypeAdapterConfig<TSource, TDestination>
.NewConfig()
.Map("PrivateDestName", "PrivateSrcName");
```

For more information about mapping non-public members, please see https://github.com/MapsterMapper/Mapster/wiki/Mapping-non-public-members.
> 更多有关于映射非公开成员的资料,请参阅 [映射非公开成员](Mapping-non-public-members.md)
### Deep destination property
### 目标多级属性映射

`Map` can be defined to map deep destination property.
使用 `Map` 方法可以为 目标多级别属性配置映射:

```csharp
TypeAdapterConfig<Poco, Dto>.NewConfig()
.Map(dest => dest.Child.Name, src => src.Name);
```

### Null propagation
### 空映射

If `Map` contains only property path, null propagation will be applied.
如果 `src.Child``null`,那么映射到 `dest.Name` 的配置不会抛出 `NullPointerException` ,而是映射空值:

```csharp
TypeAdapterConfig<Poco, Dto>.NewConfig()
.Map(dest => dest.Name, src => src.Child.Name);
```

From above example, if `src.Child` is null, mapping will return null instead of throw `NullPointerException`.

### Multiple sources

**Example 1**: Include property to Poco
### 多个源



**映射 Dto 中属性的值到 Poco**

```csharp
public class SubDto
public class Poco
{
public string Name { get; set; }
public string Extra { get; set; }
}

public class Dto
{
public string Name { get; set; }
public SubDto SubDto { get; set; }
}
public class Poco
public class SubDto
{
public string Name { get; set; }
public string Extra { get; set; }
}
```

In this case, you would like to map all properties from `Dto` to `Poco`, and also include all properties from `Dto.SubDto` to `Poco`. You can do this by just mapping `dto.SubDto` to `poco` in configuration.
如果想将 `Dto` 中的所有属性和 `Dto.SubDto` 中的所有属性映射到 `Poco`,那么可以通过配置 `dto.SubDto` 映射到 `Poco` 来实现:

```csharp
TypeAdapterConfig<Dto, Poco>.NewConfig()
.Map(poco => poco, dto => dto.SubDto);
```

**Example 2**: Mapping 2 objects to poco

In this example, you have `Dto1` and `Dto2`, and you would like to map both objects to a `Poco`. You can do this by wrapping `Dto1` and `Dto2` into a tuple. And then mapping `tuple.Item1` and `tuple.Item2` to `Poco`.

**映射两个类型到一个类型**

如果想将 `Dto1``Dto2`两个类型映射到 `Poco` 类型,那么可以通过将 `Dto1` `Dto2` 包装成一个 tuple,然后将 `tuple.Item1``tuple.Item2` 映射到 `Poco` 来实现:

```csharp
TypeAdapterConfig<(Dto1, Dto2), Poco>.NewConfig()
Expand Down
89 changes: 61 additions & 28 deletions cn/Naming-convention.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Naming convention
# 命名约定

### Flexible name
### Flexible

By default, Mapster will map property with case sensitive name. You can adjust to flexible name mapping by setting `NameMatchingStrategy.Flexible` to `NameMatchingStrategy` method. This setting will allow matching between `PascalCase`, `camelCase`, `lower_case`, and `UPPER_CASE`.
Mapster 默认在映射时会区分名称大小写,可以通过修改配置器的 `NameMatchingStrategy` 值为 `NameMatchingStrategy.Flexible` 来支持更加灵活的名称映射规则,这个映射规则支持名称在 `PascalCase`, `camelCase`, `lower_case`, `UPPER_CASE` 之间互相映射:

```csharp
//global
Expand All @@ -12,64 +12,97 @@ TypeAdapterConfig.GlobalSettings.Default.NameMatchingStrategy(NameMatchingStrate
TypeAdapterConfig<Foo, Bar>.NewConfig().NameMatchingStrategy(NameMatchingStrategy.Flexible);
```

### Ignore cases
### 忽略大小写

Flexible name could not map between `MiXcAsE` and `MixCase`, because flexible name will break `MiXcAsE` into `Mi-Xc-As-E` rather than just `Mix-Case`. In this case, we need to use `IgnoreCase` to perform case insensitive matching.
当存在一个名称为 `MiXcAsE` 到名称为 `MixCase` 的映射时, `NameMatchingStrategy.Flexible` 无法支持,因为它会把 `MiXcAsE` 处理为 `Mi-Xc-As-E`,因此我们应当使用 `NameMatchingStrategy.IgnoreCase` 来实现这个映射:

```csharp
TypeAdapterConfig.GlobalSettings.Default.NameMatchingStrategy(NameMatchingStrategy.IgnoreCase);
```

### Prefix & Replace
### 成员名称的 前缀、后缀和替换

For custom rules, you can use either `ConvertSourceMemberName` or `ConvertDestinationMemberName` up to which side you would like to convert. For example, you might would like to add `m_` to all properties.
如果存在以下的类型:

```c#
public class Poco
{
public string Name { get; set; }
public string Desc { get; set; }
public int Age { get; set; }

}

public class Dto
{
public string m_Name { get; set; }
public string m_Desc { get; set; }
public int m_Age { get; set; }
}
```

可以使用 `Map` 方法配置每个属性的映射,但这样会大大的增加编码工作量。

在这个时候就可以使用 `ConvertSourceMemberName` 配置源类型的成员命名,来实现需求:

```csharp
TypeAdapterConfig<Poco, Dto>.NewConfig()
.NameMatchingStrategy(NameMatchingStrategy.ConvertSourceMemberName(name => "m_" + name));
.NameMatchingStrategy(NameMatchingStrategy.ConvertSourceMemberName(name => "m_" + name));
```

This example is to replace foreign letter from name.
同样也可以使用 `ConvertDestinationMemberName` 配置目标类型的成员命名来实现需求:

```csharp
```c#
TypeAdapterConfig<Poco, Dto>.NewConfig()
.NameMatchingStrategy(NameMatchingStrategy.ConvertSourceMemberName(name => name.Replace("Ä", "A"));
.NameMatchingStrategy(NameMatchingStrategy.ConvertDestinationMemberName(name => name.Replace("m_", "")));
```

### Naming Convention with IDictionary<string, T>

If you would like to change case from POCO to `IDictionary<string, T>` to camelCase, you can use `ToCamelCase`. Another way around, if you would like to map `IDictionary<string, T>` back to POCO, you can use `FromCamelCase`.

```csharp


### IDictionary<string, T> 命名约定

如果想要修改 `Poco``IDictionary<string, T>` 映射 的字段命名规则为 `camelCase`,那么可以修改 `NameMatchingStrategy``NameMatchingStrategy.ToCamelCase`

```c#
TypeAdapterConfig<Poco, Dictionary<string, object>>.NewConfig()
.NameMatchingStrategy(NameMatchingStrategy.ToCamelCase);
```

如果想要从 `camelCase` 命名规则的 `IDictionary<string, T>``Poco`,那么可以修改 `NameMatchingStrategy``NameMatchingStrategy.FromCamelCase`

```csharp
TypeAdapterConfig<Dictionary<string, object>, Poco>.NewConfig()
.NameMatchingStrategy(NameMatchingStrategy.FromCamelCase);
```

NOTE: mapping from `IDictionary<string, T>` to POCO, you can also use `Flexible` or `IgnoreCase`, but both will be slower since it will scan through dictionary entries rather than lookup.
> 注意!映射 `IDictionary<string, T>` `Poco`也可以使用 `Flexible` `IgnoreCase`,在这两种命名约定规则下这两种效率比较低,
### Rule based Naming

You can change name based on rule by `GetMemberName` method. For example, if we would like to rename property based on `JsonProperty` attribute.

```csharp
TypeAdapterConfig.GlobalSettings.Default
.GetMemberName(member => member.GetCustomAttributes(true)
.OfType<JsonPropertyAttribute>()
.FirstOrDefault()?.PropertyName); //if return null, property will not be renamed
```
### 基于规则的命名

Then in your class
Mapster 支持重写成员的名称,通过 `GetMemberName` 方法可实现。

```csharp
例如,通过在类的属性上标记 `JsonProperty` 特性指定属性名称:

```c#
public class Poco
{
[JsonProperty("code")]
public string Id { get; set; }

...
}
```

With above config, `Id` will be mapped to `code`.
通过 `GetMemberName` 方法配置读取成员的 `JsonPropertyAttribute` 特性获取属性名称:

```csharp
TypeAdapterConfig.GlobalSettings.Default
.GetMemberName(member => member.GetCustomAttributes(true)
.OfType<JsonPropertyAttribute>()
.FirstOrDefault()?.PropertyName
); //if return null, property will not be renamed
```

> 注意!如果 `GetMemberName` 返回结果为空,那么将不会重写成员名称
2 changes: 1 addition & 1 deletion cn/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
##### 设置
* 自定义成员匹配逻辑
* [自定义映射](Custom-mapping.md)
* [自定义命名约束](Naming-convention.md)
* [自定义命名约定](Naming-convention.md)
* [使用特性标签配置映射](Setting-by-attributes.md)
* [忽略](Ignoring-members.md)
* [基于规则匹配](Rule-based-member-mapping.md)
Expand Down

0 comments on commit 825fcf8

Please sign in to comment.