Mapster. Как не мапить свойства равные null?

У меня есть конфигурация Mapster:

public class RegisterTelegramMapper : IRegister
{
    public void Register(TypeAdapterConfig config)
    {
        config.NewConfig<Contact, UserDto>()
            .Map(userDto => userDto.LastName, contact => contact.LastName ?? string.Empty)
            .Map(userDto => userDto.FirstName, contact => contact.FirstName ?? string.Empty)
            .Map(userDto => userDto.PhoneNumber, contact => contact.PhoneNumber ?? string.Empty)
            .IgnoreNullValues(true)
            .PreserveReference(true)
            .RequireDestinationMemberSource(true);

        config.NewConfig<Message, TelegramProfileDto>()
            .Map(tgProfileDto => tgProfileDto.ChatId, message => message.Chat.Id)
            .IgnoreNullValues(true)
            .PreserveReference(true)
            .RequireDestinationMemberSource(true);

        config.NewConfig<Message, TelegramUserProfileDto>()
            .Map(tgUserProfileDto => tgUserProfileDto.UserDto, message => message.Contact.Adapt<UserDto>())
            .Map(tgUserProfileDto => tgUserProfileDto.TelegramProfileDto, message => message.Adapt<TelegramProfileDto>())
            .IgnoreNullValues(true)
            .PreserveReference(true)
            .RequireDestinationMemberSource(true);
    }
}

Подключается она через static class:

public static class MapperConfig
{
    public static TypeAdapterConfig Configure(IRegister register)
    {
        var config = new TypeAdapterConfig();
        register.Register(config);
        TypeAdapterConfig.GlobalSettings.Compile();

        return config;
    }
}

Подключается в Program.cs:

builder.Services.AddSingleton(MapperConfig.Configure(new RegisterTelegramMapper()));
builder.Services.AddScoped<IMapper, ServiceMapper>();

Классы, которые используются в маппинге:

public class TelegramUserProfileDto
{
    public UserDto UserDto { get; set; }
    public TelegramProfileDto TelegramProfileDto { get; set; }

    public TelegramUserProfileDto()
    {
        UserDto = null!;
        TelegramProfileDto = null!;
    }
}

public class UserDto
{
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string PhoneNumber { get; set; }

    public UserDto()
    {
        LastName = string.Empty;
        FirstName = string.Empty;
        PhoneNumber = string.Empty;
    }
}

public class TelegramProfileDto
{
    public long ChatId { get; set; }
}

public class User
{
    public long Id { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string PhoneNumber { get; set; }
    public List<Car> Cars { get; set; }
    public TelegramProfile? TelegramProfile { get; set; }

    public User()
    {
        Id = default;
        LastName = string.Empty;
        FirstName = string.Empty;
        PhoneNumber = string.Empty;
        Cars = new List<Car>();
        TelegramProfile = null;
    }
}

Сам маппинг:

user = _mapper.Map<User>(telegramUserProfileDto);

Изначально свойства (string) объекта типа User инициализируются как пустые (string.Empty). В процессе маппинга приходит модель TelegramUserProfileDto, в которой подмодель UserDto имеет следующие свойства (string):

  • LastName: null
  • FirstName: "Name"
  • PhoneNumber: "Number"

В итоге это маппится в user, у которого теперь свойство LastName = null, хотя мне нужно иметь там как минимум (в худшем случае) пустую строчку.

Для этого я использую IgnoreNullValues(true), но не вижу никакой разницы в работе с ним и без него, потому что значения null всё также добавляются в результирующую модель user.

Что я сделал не так и как мне заставить Mapster оставлять свойства (string) пустыми (string.Empty)?

Заранее спасибо.


Ответы (1 шт):

Автор решения: Danila

Всё, что нужно было сделать, это применить config для метода Adapt.

public class RegisterTelegramMapper : IRegister
{
    public void Register(TypeAdapterConfig config)
    {
        config.NewConfig<Contact, UserDto>()
            .Map(userDto => userDto.LastName, contact => contact.LastName ?? string.Empty)
            .Map(userDto => userDto.FirstName, contact => contact.FirstName ?? string.Empty)
            .Map(userDto => userDto.PhoneNumber, contact => contact.PhoneNumber ?? string.Empty)
            .IgnoreNullValues(true)
            .PreserveReference(true)
            .RequireDestinationMemberSource(true);

        config.NewConfig<Message, TelegramProfileDto>()
            .Map(tgProfileDto => tgProfileDto.ChatId, message => message.Chat.Id)
            .IgnoreNullValues(true)
            .PreserveReference(true)
            .RequireDestinationMemberSource(true);

        config.NewConfig<Message, TelegramUserProfileDto>()
            .Map(tgUserProfileDto => tgUserProfileDto.UserDto, message => message.Contact.Adapt<UserDto>(config))
            .Map(tgUserProfileDto => tgUserProfileDto.TelegramProfileDto, message => message.Adapt<TelegramProfileDto>(config))
            .IgnoreNullValues(true)
            .PreserveReference(true)
            .RequireDestinationMemberSource(true);
    }
}
→ Ссылка