-
Notifications
You must be signed in to change notification settings - Fork 371
Mapster.Tool
#skip this step if you already have dotnet-tools.json
dotnet new tool-manifest
dotnet tool install Mapster.Tool
Mapster.Tool provides 3 commands
- model: generate models from entities
- extension: generate extension methods from entities
- mapper: generate mappers from interfaces
And Mapster.Tool provides following options
- -a: define input assembly
- -n: define namespace of generated classes
- -o: define output directory
add following code to your csproj
file.
<Target Name="Mapster">
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet build" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet tool restore" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster model -a "$(TargetDir)$(ProjectName).dll"" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster extension -a "$(TargetDir)$(ProjectName).dll"" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster mapper -a "$(TargetDir)$(ProjectName).dll"" />
</Target>
to generate run following command on csproj
file directory:
dotnet msbuild -t:Mapster
add following code to your csproj
file.
<Target Name="Mapster" AfterTargets="AfterBuild">
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet tool restore" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster model -a "$(TargetDir)$(ProjectName).dll"" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster extension -a "$(TargetDir)$(ProjectName).dll"" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster mapper -a "$(TargetDir)$(ProjectName).dll"" />
</Target>
add following code to your csproj
file.
<ItemGroup>
<Generated Include="**\*.g.cs" />
</ItemGroup>
<Target Name="CleanGenerated">
<Delete Files="@(Generated)" />
</Target>
to clean up run following command:
dotnet msbuild -t:CleanGenerated
If your POCOs and DTOs have the same name, you might need to generate using full type name, by add -p
flag.
<Target Name="Mapster">
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet build" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet tool restore" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster model -a "$(TargetDir)$(ProjectName).dll" -p" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster extension -a "$(TargetDir)$(ProjectName).dll" -p" />
<Exec WorkingDirectory="$(ProjectDir)" Command="dotnet mapster mapper -a "$(TargetDir)$(ProjectName).dll" -p" />
</Target>
Annotate your class with [AdaptFrom]
, [AdaptTo]
, or [AdaptTwoWays]
.
Example:
[AdaptTo("[name]Dto")]
public class Student {
...
}
Then Mapster will generate:
public class StudentDto {
...
}
By default, code generation will ignore properties that annotated [AdaptIgnore]
attribute. But you can add more settings which include IgnoreAttributes
, IgnoreNoAttributes
, IgnoreNamespaces
.
Example:
[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
}
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:
[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:
public class StudentDto {
public ICollection<DataItem> Enrollments { get; set; }
}
public class EnrollmentDto {
public string Grade { get; set; }
}
For [AdaptTo]
and [AdaptTwoWays]
, you can generate readonly properties with MapToConstructor
setting.
For example:
[AdaptTo("[name]Dto", MapToConstructor = true)]
public class Student {
public string Name { get; set; }
}
This will generate:
public class StudentDto {
public string Name { get; }
public StudentDto(string name) {
this.Name = name;
}
}
For [AdaptFrom]
, you can generate nullable properties with IgnoreNullValues
setting.
For example:
[AdaptFrom("[name]Merge", IgnoreNullValues = true)]
public class Student {
public int Age { get; set; }
}
This will generate:
public class StudentMerge {
public int? Age { get; set; }
}
For any POCOs annotate with [AdaptFrom]
, [AdaptTo]
, or [AdaptTwoWays]
, you can add [GenerateMapper]
in order to generate extension methods.
Example:
[AdaptTo("[name]Dto"), GenerateMapper]
public class Student {
...
}
Then Mapster will generate:
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 => ...
}
You can also generate extension methods and add extra settings from configuration.
public class MyRegister : IRegister
{
public void Register(TypeAdapterConfig config)
{
config.NewConfig<TSource, TDestination>()
.GenerateMapper(MapType.Map | MapType.MapToTarget);
}
}
Annotate your interface with [Mapper]
in order for tool to pickup for generation.
This is example interface.
[Mapper]
public interface IProductMapper
{
ProductDTO Map(Product customer);
}
You can add multiple members as you want. All member names are flexible, but signature must be in following patterns:
[Mapper]
public interface ICustomerMapper
{
//for queryable
Expression<Func<Customer, CustomerDTO>> ProjectToDto { get; }
//map from POCO to DTO
CustomerDTO MapToDto(Customer customer);
//map to existing object
Customer MapToExisting(CustomerDTO dto, Customer customer);
}
If you have configuration, it must be in IRegister
public class MyRegister : IRegister
{
public void Register(TypeAdapterConfig config)
{
config.NewConfig<TSource, TDestination>();
}
}
- Configuration
- Config inheritance
- Config instance
- Config location
- Config validation & compilation
- Config for nested mapping
- Custom member matching logic
- Constructor mapping
- Before & after mapping
- Setting values
- Shallow & merge mapping
- Recursive & object references
- Custom conversion logic
- Inheritance