When working with objects, developers often need to transform one object into another. This is especially common when working with DTO models, business logic layers, and data coming from external systems.
To automate such transformations, libraries like AutoMapper and Mapster come to the rescue. But which one should you choose? In this article, we’ll discuss their features, compare performance and usability, and walk through practical usage examples, including complex cases such as mapping classes with different property names and enums.
What is AutoMapper?
AutoMapper is one of the most popular libraries for object-to-object mapping in .NET. Its primary goal is to reduce the amount of manual transformation code — you define mapping rules, and the library handles the rest.
Key Advantages:
- Configuration is done through profiles.
- Supports mapping of complex objects, nested structures, and collections.
- Integrates well with popular ORM tools like Entity Framework.
- Allows configuration for enum and other type mappings.
Drawbacks:
- Performance can be slower compared to other libraries, as it often relies on reflection.
- Mapping configurations for complex models can become verbose.
What is Mapster?
Mapster is a newer library that emphasizes ease of use and better performance. It generates mapping code at compile-time, saving runtime overhead and offering better efficiency.
Key Advantages:
- Simple and minimalistic configuration requiring less code.
- High performance due to the lack of reliance on reflection.
- Supports complex types (including collections and enums) with a clean configuration.
- Mapping definitions can be embedded directly within class models.
Drawbacks:
- Less widely known compared to AutoMapper, meaning fewer tutorials or resources available.
- May require more control for advanced mapping cases.
Examples of Usage
1. Mapping Classes with Identical Property Names
If the property names in source and destination classes match, no additional configuration is needed.
AutoMapper:
using AutoMapper;
public class Source
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Destination
{
public string Name { get; set; }
public int Age { get; set; }
}
var config = new MapperConfiguration(cfg => cfg.CreateMap<Source, Destination>());
var mapper = config.CreateMapper();
var source = new Source { Name = "John", Age = 30 };
var destination = mapper.Map<Destination>(source);
// Result:
// destination.Name = "John", destination.Age = 30
Mapster:
using Mapster;
public class Source
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Destination
{
public string Name { get; set; }
public int Age { get; set; }
}
var source = new Source { Name = "John", Age = 30 };
var destination = source.Adapt<Destination>();
// Result:
// destination.Name = "John", destination.Age = 30
2. Mapping Classes with Different Property Names and Enums
It is common to encounter cases where:
- Source and destination objects have properties with different names.
- Properties are represented using enums that need to be transformed into other enums (or other values).
AutoMapper:
using AutoMapper;
// Enums
public enum UserStatus
{
Active,
Inactive
}
public enum UserDtoStatus
{
ActiveUser,
InactiveUser
}
// Classes
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public UserStatus Status { get; set; }
}
public class UserDto
{
public string GivenName { get; set; }
public string FamilyName { get; set; }
public UserDtoStatus Status { get; set; }
}
// Configuration
var config = new MapperConfiguration(cfg =>
{
// Enum mapping
cfg.CreateMap<UserStatus, UserDtoStatus>()
.ConvertUsing(src => src == UserStatus.Active ? UserDtoStatus.ActiveUser : UserDtoStatus.InactiveUser);
// Property mapping (different property names)
cfg.CreateMap<User, UserDto>()
.ForMember(dest => dest.GivenName, opt => opt.MapFrom(src => src.FirstName))
.ForMember(dest => dest.FamilyName, opt => opt.MapFrom(src => src.LastName));
});
var mapper = config.CreateMapper();
var user = new User { FirstName = "John", LastName = "Doe", Status = UserStatus.Active };
var userDto = mapper.Map<UserDto>(user);
// Result:
// userDto.GivenName = "John"
// userDto.FamilyName = "Doe"
// userDto.Status = UserDtoStatus.ActiveUser
Mapster:
using Mapster;
// Enums
public enum UserStatus
{
Active,
Inactive
}
public enum UserDtoStatus
{
ActiveUser,
InactiveUser
}
// Classes
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public UserStatus Status { get; set; }
}
public class UserDto
{
public string GivenName { get; set; }
public string FamilyName { get; set; }
public UserDtoStatus Status { get; set; }
}
// Configuration
TypeAdapterConfig<UserStatus, UserDtoStatus>.NewConfig()
.MapWith(src => src == UserStatus.Active ? UserDtoStatus.ActiveUser : UserDtoStatus.InactiveUser);
TypeAdapterConfig<User, UserDto>.NewConfig()
.Map(dest => dest.GivenName, src => src.FirstName)
.Map(dest => dest.FamilyName, src => src.LastName);
var user = new User { FirstName = "John", LastName = "Doe", Status = UserStatus.Active };
var userDto = user.Adapt<UserDto>();
// Result:
// userDto.GivenName = "John"
// userDto.FamilyName = "Doe"
// userDto.Status = UserDtoStatus.ActiveUser
3. Performance: Which is Faster?
One of the most frequently discussed topics is the performance of these libraries. Benchmarks show that Mapster is generally faster for large datasets due to compile-time mapping:
-
AutoMapper: ~20–50 ms for mapping 10,000 objects.
-
Mapster: ~5–20 ms for mapping 10,000 objects.
For larger datasets, the difference becomes more noticeable. However, both tools are performant enough for most average use cases.
For larger datasets, the difference becomes more noticeable. However, both tools are performant enough for most average use cases.
Conclusion
Both AutoMapper and Mapster are excellent tools for object mapping, but their features may influence your choice based on your specific needs:
-
Choose AutoMapper if you prefer profile-based configurations, value flexibility, and want a mature, time-tested tool.
-
Opt for Mapster if you need maximum performance, a minimalistic setup, and a modern approach.
In the end, both libraries are capable of handling advanced mapping scenarios efficiently.