-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
28 changed files
with
1,586 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,3 +12,7 @@ | |
|
||
## Documents | ||
|
||
|
||
|
||
[中文文档](cn/README.md) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Async | ||
|
||
### Async support | ||
|
||
PM> Install-Package Mapster.Async | ||
|
||
This plugin allows you to perform async operation for mapping | ||
|
||
##### Setup | ||
|
||
Use `AfterMappingAsync` to setup async operation | ||
|
||
```csharp | ||
config.NewConfig<Poco, Dto>() | ||
.AfterMappingAsync(async (poco, dto) => | ||
{ | ||
var userManager = MapContext.Current.GetService<UserManager>(); | ||
var user = await userManager.FindByIdAsync(poco.UserId); | ||
dto.UserName = user.Name; | ||
}); | ||
``` | ||
|
||
##### Mapping | ||
|
||
Then map asynchronously with `AdaptToTypeAsync`. | ||
|
||
```csharp | ||
var dto = await poco.BuildAdapter() | ||
.AdaptToTypeAsync<Dto>(); | ||
``` | ||
|
||
|
||
Or like this, if you use mapper instance. | ||
|
||
```csharp | ||
var dto = await _mapper.From(poco) | ||
.AdaptToTypeAsync<Dto>(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
# Attribute base Code generation | ||
|
||
### Generate models | ||
|
||
Annotate your class with `[AdaptFrom]`, `[AdaptTo]`, or `[AdaptTwoWays]`. | ||
|
||
Example: | ||
```csharp | ||
[AdaptTo("[name]Dto")] | ||
public class Student { | ||
... | ||
} | ||
``` | ||
|
||
Then Mapster will generate: | ||
```csharp | ||
public class StudentDto { | ||
... | ||
} | ||
``` | ||
|
||
#### Ignore some properties on generation | ||
|
||
By default, code generation will ignore properties that annotated `[AdaptIgnore]` attribute. But you can add more settings which include `IgnoreAttributes`, `IgnoreNoAttributes`, `IgnoreNamespaces`. | ||
|
||
Example: | ||
```csharp | ||
[AdaptTo("[name]Dto", IgnoreNoAttributes = new[] { typeof(DataMemberAttribute) })] | ||
public class Student { | ||
|
||
[DataMember] | ||
public string Name { get; set; } //this property will be generated | ||
public string LastName { get; set; } //this will not be generated | ||
} | ||
``` | ||
|
||
#### Change property types | ||
|
||
By default, if property type annotated with the same adapt attribute, code generation will forward to that type. (For example, `Student` has `ICollection<Enrollment>`, after code generation `StudentDto` will has `ICollection<EnrollmentDto>`). | ||
|
||
You can override this by `[PropertyType(typeof(Target))]` attribute. This annotation can be annotated to either on property or on class. | ||
|
||
For example: | ||
```csharp | ||
[AdaptTo("[name]Dto")] | ||
public class Student { | ||
public ICollection<Enrollment> Enrollments { get; set; } | ||
} | ||
|
||
[AdaptTo("[name]Dto"), PropertyType(typeof(DataItem))] | ||
public class Enrollment { | ||
[PropertyType(typeof(string))] | ||
public Grade? Grade { get; set; } | ||
} | ||
``` | ||
|
||
This will generate: | ||
```csharp | ||
public class StudentDto { | ||
public ICollection<DataItem> Enrollments { get; set; } | ||
} | ||
public class EnrollmentDto { | ||
public string Grade { get; set; } | ||
} | ||
``` | ||
|
||
#### Generate readonly properties | ||
|
||
For `[AdaptTo]` and `[AdaptTwoWays]`, you can generate readonly properties with `MapToConstructor` setting. | ||
|
||
For example: | ||
```csharp | ||
[AdaptTo("[name]Dto", MapToConstructor = true)] | ||
public class Student { | ||
public string Name { get; set; } | ||
} | ||
``` | ||
|
||
This will generate: | ||
```csharp | ||
public class StudentDto { | ||
public string Name { get; } | ||
|
||
public StudentDto(string name) { | ||
this.Name = name; | ||
} | ||
} | ||
``` | ||
|
||
#### Generate nullable properties | ||
|
||
For `[AdaptFrom]`, you can generate nullable properties with `IgnoreNullValues` setting. | ||
|
||
For example: | ||
```csharp | ||
[AdaptFrom("[name]Merge", IgnoreNullValues = true)] | ||
public class Student { | ||
public int Age { get; set; } | ||
} | ||
``` | ||
|
||
This will generate: | ||
```csharp | ||
public class StudentMerge { | ||
public int? Age { get; set; } | ||
} | ||
``` | ||
|
||
### Generate extension methods | ||
|
||
#### Generate using `[GenerateMapper]` attribute | ||
For any POCOs annotate with `[AdaptFrom]`, `[AdaptTo]`, or `[AdaptTwoWays]`, you can add `[GenerateMapper]` in order to generate extension methods. | ||
|
||
Example: | ||
```csharp | ||
[AdaptTo("[name]Dto"), GenerateMapper] | ||
public class Student { | ||
... | ||
} | ||
``` | ||
|
||
Then Mapster will generate: | ||
```csharp | ||
public class StudentDto { | ||
... | ||
} | ||
public static class StudentMapper { | ||
public static StudentDto AdaptToDto(this Student poco) { ... } | ||
public static StudentDto AdaptTo(this Student poco, StudentDto dto) { ... } | ||
public static Expression<Func<Student, StudentDto>> ProjectToDto => ... | ||
} | ||
``` | ||
|
||
#### Configuration | ||
If you have configuration, it must be in `IRegister` | ||
|
||
```csharp | ||
public class MyRegister : IRegister | ||
{ | ||
public void Register(TypeAdapterConfig config) | ||
{ | ||
config.NewConfig<TSource, TDestination>(); | ||
} | ||
} | ||
``` | ||
|
||
#### Generate using configuration | ||
|
||
You can also generate extension methods and add extra settings from configuration. | ||
|
||
```csharp | ||
public class MyRegister : IRegister | ||
{ | ||
public void Register(TypeAdapterConfig config) | ||
{ | ||
config.NewConfig<TSource, TDestination>() | ||
.GenerateMapper(MapType.Map | MapType.MapToTarget); | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# 配置位置 | ||
|
||
### 入口 | ||
|
||
映射配置应该只初始化并且只进行一次配置。因此在编写代码的时候不能将映射配置和映射调用放在同一个地方。 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Custom conversion logic | ||
|
||
### Custom type conversion | ||
|
||
In some cases, you may want to have complete control over how an object is mapped. You can register specific transformations using the `MapWith` method. | ||
|
||
```csharp | ||
//Example of transforming string to char[]. | ||
TypeAdapterConfig<string, char[]>.NewConfig() | ||
.MapWith(str => str.ToCharArray()); | ||
``` | ||
|
||
`MapWith` also useful if you would like to copy instance rather than deep copy the object, for instance, `JObject` or `DbGeography`, these should treat as primitive types rather than POCO. | ||
|
||
```csharp | ||
TypeAdapterConfig<JObject, JObject>.NewConfig() | ||
.MapWith(json => json); | ||
``` | ||
|
||
In case you would like to combine `MapWith` with other settings, for example, `PreserveReference`, `Include`, or `AfterMapping`, you can pass `applySettings` to true. | ||
|
||
```csharp | ||
TypeAdapterConfig<ComplexPoco, ComplexDto>.NewConfig() | ||
.PreserveReference(true) | ||
.MapWith(poco => poco.ToDto(), applySettings: true); | ||
``` | ||
|
||
### Custom mapping data to existing object | ||
|
||
You can control mapping to existing object logic by `MapToTargetWith`. For example, you can copy data to existing array. | ||
|
||
```csharp | ||
TypeAdapterConfig<string[], string[]>.NewConfig() | ||
.MapToTargetWith((src, dest) => Array.Copy(src, dest, src.Length)); | ||
``` | ||
|
||
NOTE: if you set `MapWith` setting but no `MapToTargetWith` setting, Mapster will use logic from `MapWith` setting. | ||
|
||
### Custom actions after mapping | ||
|
||
You might not need to specify custom mapping logic completely. You can let Mapster do the mapping, and you do logic where Mapster cannot cover by using `AfterMapping`. | ||
|
||
```csharp | ||
TypeAdapterConfig<Poco, Dto>.NewConfig() | ||
.AfterMapping((src, dest) => SpecialSetFn(src, dest)); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# Custom mapping | ||
|
||
### Custom member mapping | ||
|
||
You can customize how Mapster maps values to a property. | ||
|
||
```csharp | ||
TypeAdapterConfig<TSource, TDestination> | ||
.NewConfig() | ||
.Map(dest => dest.FullName, | ||
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" | ||
``` | ||
|
||
### Mapping with condition | ||
|
||
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> | ||
.NewConfig() | ||
.Map(dest => dest.FullName, src => "Sig. " + src.FullName, srcCond => srcCond.Country == "Italy") | ||
.Map(dest => dest.FullName, src => "Sr. " + src.FullName, srcCond => srcCond.Country == "Spain") | ||
.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). | ||
|
||
### Mapping to non-public members | ||
|
||
`Map` command can map to private member by specify name of the members. | ||
|
||
```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. | ||
|
||
### Deep destination property | ||
|
||
`Map` can be defined to map deep destination property. | ||
|
||
```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. | ||
|
||
```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 | ||
|
||
```csharp | ||
public class SubDto | ||
{ | ||
public string Extra { get; set; } | ||
} | ||
public class Dto | ||
{ | ||
public string Name { get; set; } | ||
public SubDto SubDto { get; set; } | ||
} | ||
public class Poco | ||
{ | ||
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. | ||
|
||
```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`. | ||
|
||
```csharp | ||
TypeAdapterConfig<(Dto1, Dto2), Poco>.NewConfig() | ||
.Map(dest => dest, src => src.Item1) | ||
.Map(dest => dest, src => src.Item2); | ||
``` |
Oops, something went wrong.