Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mapster re-writing value when mapping resulting in wrong destination type #684

Open
luczito opened this issue Mar 12, 2024 · 2 comments
Open

Comments

@luczito
Copy link

luczito commented Mar 12, 2024

I have the following classes and patterns that Mapster can't work with. Specifically the pattern for overwriting the DerivedPayment in each of the derived classes.
When debugging it shows that the "setter" gets the correct value, Dom/DtoDerivedPayment. But when the "getter" is called this value is somehow overwritten to the base instance of Dom/DtoPayment instead, resulting in a "System.InvalidCastException : Unable to cast object of type 'DomPayment' to type 'DomDerivedPayment'."

using System.Reflection;
using Mapster;
using NUnit.Framework;

public abstract class DomBase
{
    public DomPayment Payment { get; set; }
}

public class DomDerived : DomBase
{
    public new DomDerivedPayment Payment
    {
        get => (DomDerivedPayment)base.Payment;
        set => base.Payment = (DomPayment)value;
    }
}

public class DomPayment
{
    public bool Prop { get; set; }
}

public class DomDerivedPayment : DomPayment
{
    public bool Test { get; set; }
}

public abstract class DtoBase
{
    public DtoPayment Payment { get; set; }
}

public class DtoDerived : DtoBase
{
    public new DtoDerivedPayment Payment
    {
        get => (DtoDerivedPayment)base.Payment;
        set => base.Payment = (DtoPayment)value;
    }
}

public class DtoPayment
{
    public bool Prop { get; set; }
}

public class DtoDerivedPayment : DtoPayment
{
    public bool Test { get; set; }
}

public class Mapping : IRegister
{
    public void Register(TypeAdapterConfig config)
    {
        config.NewConfig<DomBase, DtoBase>()
            .Include<DomDerived, DtoDerived>();

        config.NewConfig<DtoBase, DomBase>()
            .Include<DtoDerived, DomDerived>();
        
        config.NewConfig<DtoPayment, DomPayment>()
            .Include<DtoDerivedPayment, DomDerivedPayment>();

        config.NewConfig<DomPayment, DtoPayment>()
            .Include<DomDerivedPayment, DtoDerivedPayment>();
    }
}

[TestFixture]
public class MapsterTests
{
    [Test]
    public void DtoToDomain()
    {
        var config = TypeAdapterConfig.GlobalSettings;
        config.Scan(Assembly.Load("test.repo"));
        var dto = new DtoDerived();
        dto.Payment = new DtoDerivedPayment();
        dto.Payment.Prop = true;
        dto.Payment.Test = true;
        var domain = dto.Adapt<DomDerived>();
        Assert.That(domain.Payment.Prop, Is.EqualTo(dto.Payment.Prop));
    }

    [Test]
    public void DomainToDto()
    {
        var domain = new DomDerived();
        domain.Payment = new DomDerivedPayment();
        var dto = domain.Adapt<DtoDerived>();
        Assert.That(dto.Payment.Prop, Is.EqualTo(domain.Payment.Prop));
    }
}
@coolqingcheng
Copy link

coolqingcheng commented May 15, 2024

I also encountered it. The Id of my parent class is int, and the subclass uses new to modify the guid, and a type conversion error is reported.

  ---> Mapster.CompileException: Error while compiling
source=System.Nullable`1[System.Guid]
destination=System.Int32
type=Map

@coolqingcheng
Copy link

Even if I configure ignore, I still get an error

 config.ForType<EditUserModel, User>()
            .IgnoreIf((model, user) => model.Id == null, a => a.Id)
            .IgnoreNullValues(true);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants