MapsterMapper / Mapster

A fast, fun and stimulating object to object Mapper
MIT License
4.29k stars 327 forks source link

Mapster fail to use user-defined explicit or implicit conversion operators from target type #569

Open Orace opened 1 year ago

Orace commented 1 year ago

From this SO question.

Given the type Id:

public class Id
{
    private readonly Guid _guid;

    public Id(Guid id) => _guid = id;

    public static implicit operator Id(Guid value) => new(value);
    public static implicit operator Guid(Id value) => value._guid;

    public override string ToString() => _guid.ToString();
}

Despite the implicit conversion Mapster fail to map a Guid to an Id:

public class PocoWithGuid
{
    public Guid Id { get; init; }
}

public class PocoWithId
{
    public Id Id { get; init; }
}

var guid = Guid.NewGuid();

var pocoWithGuid1 = new PocoWithGuid { Id = guid };
Console.WriteLine(pocoWithGuid1.Id);    // 9c29424a-3c7b-4982-b301-84cc7ac41bc6

// Guid to Id fail
var pocoWithId1 = pocoWithGuid1.Adapt<PocoWithId>();
Console.WriteLine(pocoWithId1.Id);      // 00000000-0000-0000-0000-000000000000

var pocoWithId2 = new PocoWithId { Id = new Id(guid) };
Console.WriteLine(pocoWithId2.Id);      // 9c29424a-3c7b-4982-b301-84cc7ac41bc6

// Id to Guid works
var pocoWithGuid2 = pocoWithId2.Adapt<PocoWithGuid>();
Console.WriteLine(pocoWithGuid2.Id);    // 9c29424a-3c7b-4982-b301-84cc7ac41bc6

Demo code available here.

andrerav commented 1 year ago

@Orace Which version of Mapster are you using?

Orace commented 1 year ago

@andrerav, the last one available on NuGet: 7.3.0, the demo code run on .Net7

andrerav commented 1 year ago

Could you try the latest prerelease please?

DocSvartz commented 11 months ago

@Orace @andrerav

This is #537
Id Detect as Record

adapt Guid to Id is Not possible The following reasons: 1) Members of Guid and Id is not match 2) ID does not contain a constructor through which an ID can be created based on the members of the Guid

then: 1) A new guid instance is created.
2) Which then initializes a new instance of Id through the constructor

Having learned this, I added the constructor from the Guid to ID and everything worked.

And naming of Member TSource and parameters in ctor TDestination Must be equal according to the used Naming convention

public Id(uint a, ushort b, ushort c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k)
{
    _guid = new Guid(a,b, c, d, e, f, g, h, i, j, k);
}
DocSvartz commented 11 months ago

From then TDistination detect as class it work

Orace commented 11 months ago

Could you try the latest prerelease please?

@andrerav, It fails with 7.4.0 too.