Ignore on base class mapper ignores on inherited class mapper
I've noticed what I consider to be an issue with Mapster and can't see another issue related to this. It may also be a lack of understanding on my part. So apologies if either of those are the case!
The issue is that when you have a mapper for a base class to a mapped class and a mapper for a class that inherits from that base class to the same mapped class, then ignores on base -> mapped also ignore on inherited -> mapped. Code to reproduce is given below. I can change the base class mapper to map to the default value instead of using .Ignore and it works as I would expect it to. I realise that I could probably set RequireDestinationMemberSource to false but in the project where I originally discovered this issue we want to have RequireDestinationMemberSource = true.
My expectation would be that I could ignore something in the mapper for the base class but have some code to map that field for the inherited class.
In the relevant project I've modified the base class mapper to map to default values for fields that will be mapped in the derived class but I would prefer to use .Ignore. Is this an issue or is there something else I can use in Mapster to achieve the required effect? I've scanned through the documentation and can't find any solution to this that works for me.
Code to reproduce the issue
// Program.cs
using Mapster;
TypeAdapterConfig.GlobalSettings
.NewConfig<BaseClass, MappedClass>()
.Map(dest => dest.Base, src => src.Base)
.Ignore(dest => dest.Inherited!);
TypeAdapterConfig.GlobalSettings
.NewConfig<InheritedClass, MappedClass>()
.Map(dest => dest.Base, src => src.Base)
.Map(dest => dest.Inherited, src => src.Inherited);
var inheritedMapped = new InheritedClass
{
Base = "base",
Inherited = "inherited"
}.Adapt<MappedClass>();
Console.WriteLine("inherited class: {0}", inheritedMapped.Inherited);
// output: inherited class:
// expected output: inherited class: inherited
internal class BaseClass
{
public string? Base { get; set; }
}
internal class InheritedClass : BaseClass
{
public string? Inherited { get; set; }
}
internal class MappedClass
{
public string? Base { get; set; }
public string? Inherited { get; set; }
}
Hello @thomas-hockings-cs
I don't quite understand what exactly you want to get?
In your example, the Base class does not contain the Inherited field
When converting the Base Class to the MappedClass, nothing will be transferred anyway.
.Ignore(dest => dest.Inherited!);
With this directive you prohibit the MappedClass from mapping anything to this field Inherited for your class hierarchy.(it real strange 🤔)
*Update
With this directive you prohibit the
MappedClassfrom mapping anything to this fieldInheritedfor your class hierarchy.(it real strange 🤔)
This is the default behavior
You must use TypeAdapterConfig.GlobalSettings.AllowImplicitDestinationInheritance = false; but then you will lose the entire mapping configuration from the base class
Perhaps you wanted this result?
[TestMethod]
public void IgnogbaseClass()
{
TypeAdapterConfig.GlobalSettings
.NewConfig<BaseClass621, MappedClass621>()
.Map(dest => dest.Base, src => src.Base)
.Map(dest=> dest.Inherited, src=> src.Inherited, src=> src.GetType() != typeof(BaseClass621))
.IgnoreNullValues(true);;
var _BaseClass = new BaseClass621 { Base = "Me", Inherited = "Hello" };
var _TestBaseClassAdapt = _BaseClass.Adapt<MappedClass621>(); // { Base = "Me", Inherited = null }
var inheritedMapped = new InheritedClass621 // { Base = "base", Inherited = "inherited" }
{
Base = "base",
Inherited = "inherited"
}.Adapt<MappedClass621>();
var MappedClassToUpdate = new MappedClass621() { Base = "Update", Inherited = "Update" };
var _NoUpdate = _BaseClass.Adapt(MappedClassToUpdate); // { Base = "Me", Inherited = Update }; // it work with .IgnoreNullValues(true);
}
internal class BaseClass621
{
public string? Base { get; set; }
public string? Inherited { get; set; }
}
internal class InheritedClass621 : BaseClass621
{
}
internal class MappedClass621
{
public string? Base { get; set; }
public string? Inherited { get; set; }
}