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:

Drawbacks:

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:

Drawbacks:

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:

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:

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:

In the end, both libraries are capable of handling advanced mapping scenarios efficiently.