Repository navigation
Polymorphic mapping of nested property to null property. #794
Copy link
Copy link
Closed
Description
Hi all!
Mapster 7.4.0
I encountered some strange behavior with mapping of polymorphic nested properties.
The task is to map a nested polymorhic property of source (DTO) to the nested polymorphic property of destination.
Expected result of mapping for actual types is.
BaseDTO -> Base
DerivedDTO-> Derived
When destination nested property is null it is always mapped as base class even when the source nested property is derived class.
DerivedDTO-> Derived - not works when destination property is null
May be it is expected, but it looks like a bug for me. Or may be there is a mistake in my configuration?
public class Base
{
public string SomeBaseProperty { get; set; }
}
public class BaseDTO
{
public string SomeBasePropertyDTO { get; set; }
}
public class Derived : Base
{
public string SomeDerivedProperty { get; set; }
}
public class DerivedDTO : BaseDTO
{
public string SomeDerivedPropertyDTO { get; set; }
}
public class Container
{
public Base Nested { get; set; }
}
public class ContainerDTO
{
public BaseDTO NestedDTO { get; set; }
}
config
.NewConfig<ContainerDTO, Container>()
.Map(dest => dest.Nested, src => src.NestedDTO )
.IgnoreNonMapped(true)
.IgnoreNullValues(true);
config
.NewConfig<BaseDTO, Base>()
.Map(dest => dest.SomeBaseProperty , src => src.SomeBasePropertyDTO)
.Include<DerivedDTO, Base>()
.IgnoreNonMapped(true)
.IgnoreNullValues(true);
config
.NewConfig<DerivedDTO, Derived>()
.Map(dest => dest.SomeDerivedProperty , src => src.SomeDerivedPropertyDTO)
.IgnoreNonMapped(true)
.IgnoreNullValues(true);
config
.NewConfig<DerivedDTO, Base>()
.MapWith(src => src.Adapt<Derived>());
//Case 1 (works)
var container = new();
var containerDTO = new();
//Nested is populated with Base
container.Nested = new();
containerDTO.NestedDTO = new DerivedDTO();
//Polymorphism works for Nested property
mapper.Map<ContainerDTO, Container>(containerDTO, container);
//Case 2 (does not work)
var container = new();
var containerDTO = new();
//Nested is null
container.Nested = null;
containerDTO.NestedDTO = new DerivedDTO();
//Polymorphism does not work for Nested property. It is always Base.
mapper.Map<ContainerDTO, Container>(containerDTO, container);
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
DocSvartz commentedon Apr 29, 2025
Yes, this does happen.
But it most likely has nothing to do with Polymorphic mapping.
Most likely, this is the work of the protection mechanism against mapping to Null.
In your case (MapToTarget), the state of the internal fields of the Destination instance should be replaced with the transformed values of the Source.
But since this is null, to avoid null Reference exception -> an instance of the declared variable type is created (in your case it is Base).
This can be fixed, but we just need to understand what behavior is expected in this case?
vchc commentedon May 1, 2025
I expect some consistency here. For collections it works just fine. You can have a null or empty collection property on the destination and polymorphic mapping will work with my configuration.
I still think it is a bug.
Moreover I provide construction rule with
and expect that the null property will be handled with my rule.
So my expectations are:
DocSvartz commentedon May 2, 2025
@vchc
The consistency is actually there, it's just not what you expect.
MapToTarget is updating an existing instance of the destination type with the state of the source instance.
MapToTarget does not work for collections (I don't know if this was originally intended or didn't have time to do it)
I found where it happened. Tests are currently running. If there are no other errors, it will work :)
vchc commentedon May 3, 2025
Thanks for the PR @DocSvartz !