MapsterMapper / Mapster

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

PreserveReference is using the src PropertyName to set the Destination property. #681

Open OFark opened 7 months ago

OFark commented 7 months ago
public sealed record FirstType()
{
    public bool ChargeToAccount {get; init;}
    public string Name {get; set;}
}

public sealed record SecondType()
{
    public bool CanChargeToAccount { get; init; }
    public string Name { get; set; }
}

If I run:

TypeAdapterConfig.GlobalSettings.ForType<FirstType, SecondType>()
           .PreserveReference(true).Map(st => st.CanChargeToAccount, ft => ft.ChargeToAccount);

    var ft = new FirstType() { ChargeToAccount = true, Name = "Jeff"};

    var st = ft.Adapt<SecondType>();    

The generated script is:

public UserQuery.SecondType Main(UserQuery.FirstType p1)
{
    if (p1 == null)
    {
        return null;
    }
    MapContextScope scope = new MapContextScope();

    try
    {
        object cache;

        Dictionary<ReferenceTuple, object> references = scope.Context.References;
        ReferenceTuple key = new ReferenceTuple(p1, typeof(UserQuery.SecondType));

        if (references.TryGetValue(key, out cache))
        {
            return (UserQuery.SecondType)cache;
        }
        UserQuery.SecondType result = new UserQuery.SecondType();
        references[key] = (object)result;

        typeof(UserQuery.SecondType).GetProperty("ChargeToAccount").SetValue(result, (object)p1.ChargeToAccount);
        result.Name = p1.Name;
        return result;
    }
    finally
    {
        scope.Dispose();
    }

}

note this line: typeof(UserQuery.SecondType).GetProperty("ChargeToAccount").SetValue(result, (object)p1.ChargeToAccount);

should be typeof(UserQuery.SecondType).GetProperty("CanChargeToAccount").SetValue(result, (object)p1.ChargeToAccount);

CanChargeToAccount is coming through as ChargeToAccount which isn't a valid property for SecondType.

FYI Mapster 7.3.0 produces the right script:

public UserQuery.SecondType Main(UserQuery.FirstType p1)
{
    if (p1 == null)
    {
        return null;
    }
    MapContextScope scope = new MapContextScope();

    try
    {
        object cache;

        Dictionary<ReferenceTuple, object> references = scope.Context.References;
        ReferenceTuple key = new ReferenceTuple(p1, typeof(UserQuery.SecondType));

        if (references.TryGetValue(key, out cache))
        {
            return (UserQuery.SecondType)cache;
        }
        UserQuery.SecondType result = new UserQuery.SecondType();
        references[key] = (object)result;

        result.CanChargeToAccount = p1.ChargeToAccount;
        result.Name = p1.Name;
        return result;
    }
    finally
    {
        scope.Dispose();
    }

}