Mapster маппинг на поле с объектом с несколькими конструкторами без дефолтного

Разбираюсь с Mappster - есть такие классы:

class In
{
    public string A;
    public string B;
    public string C;
}

class Out
{
    public Sub Sub;
    public string C;
}

class Sub
{
    public string A; 
    public string B;
    
    public Sub(string a, string b)
        =>(A,B) = (a,b);
}

Задаю правила:

var mapper = new Mapper();

mapper.Config
    .ForType<In, Out>()
    .Map(@out=> @out.Sub, @in => new Sub(@in.A, @in.B));

Если замапить сейчас все нормально, но если добавить в класс Sub еще один конструктор (допустим public Sub(string a)=> A=a;) Маппинг отвалится с ошибкой

Error while compiling
source=UserQuery+In
destination=UserQuery+Out
type=Map

Error while compiling
source=UserQuery+Sub
destination=UserQuery+Sub
type=Map
No default constructor for type 'Sub', please use 'ConstructUsing' or 'MapWith'

Почитал документацию, попробовал так сяк и 'ConstructUsing' и 'MapWith' - не подошли (или, что вероятнее, я что-то не так делаю).


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

Автор решения: Alexander Petrov
using MapsterMapper;

static class MapperExtensions
{
    public static Out Map(this IMapper mapper, In @in)
    {
        return new Out
        {
            Sub = new Sub(@in.A, @in.B),
            C = @in.C
        };
    }
}

Проверяем:

In i = new In { A = "a", B = "b", C = "c" };

IMapper mapper = new Mapper();

Out o = mapper.Map(i);

Console.WriteLine(o.Sub.A + " " + o.Sub.B + " " + o.C);

Я всегда считал и продолжаю считать, что любая утилита/библиотека должна упрощать написание кода. Автоматические мапперы можно применять, но только до тех пор, пока они делают свою работу автоматически. Как только приходится описывать маппинг вручную в конфиге маппера, то лучше от него отказаться.

В показанном мной примере ручной маппинг элементарен. В то время как конфиг с описанием правил для маппера в несколько раз больше. Так зачем писать больше?

The reasons behind why I don't use AutoMapper - замечательная статья (и вообще блог хороший), рекомендую к прочтению. В комментариях ссылка на ответ автора этого АвтоМаппера, где он юлит, но в итоге признаёт, что чаще всего нет смысла использовать его детище.

→ Ссылка
Автор решения: srvr4vr

Нашел, достаточно в конфиге добавить такое

config.ForType<Sub, Sub>().MapToConstructor(true);

Тогда сработает даже мой специфический кейс:

void Main()
{
    var mapper = new Mapper();
    
    var config = mapper.Config;

    config
        .ForType<In, Out>()
        .Map(@out => @out.Sub, @in => new Sub(@in.A, @in.B))
        .Map(@out => @out.Sub2, @in => new Sub(@in.A2, @in.B2));
        
    config.ForType<Sub, Sub>().MapToConstructor(true);
    
    var @in = new In
    {
        A = "A1",
        A2 = "A2",
        B = "B1",
        B2 = "B2",
        C ="Cfff"
    };
    
    @in.Dump();
        
    var @out = mapper.Map<Out>(@in);
    
    @out.Dump();
}

class In
{
    public string A;
    public string B;
    public string A2;
    public string B2;
    public string C;
}

class Out
{
    public Sub Sub;
    public Sub Sub2;

    public string C;
}

class Sub
{
    public string A;
    public string B;

    public Sub(string a, string b)
        => (A, B) = (a, b);

    public Sub(string a)
        => (A, B) = (a, null);
}
→ Ссылка