
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.
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.
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.
If the property names in source and destination classes match, no additional configuration is needed.
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:
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
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
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.
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.