Mapster.Tool initialises property twice if property in derived class hides base class property
Mapster.Tool initialises property twice if property in derived class hides base class property.
Example: Declaration:
public class Src
{
public MyDateTime DateTime { get; set; }
}
public class DstBase
{
public DateTime? DateTime { get; set; }
}
public class Dst:DstBase
{
public new MyDateTime DateTime { get; set; }
}
Mapper configuration:
config.ForType<Src, Dst>()
.GenerateMapper(MapType.Map);
What gets generated:
public static MapsterBug.Dst AdaptToDst(this MapsterBug.Src p1)
{
return p1 == null ? null : new MapsterBug.Dst()
{
DateTime = p1.DateTime == null ? null : new MapsterBug.MyDateTime(p1.DateTime.DateTime),
DateTime = (System.DateTime?)p1.DateTime.DateTime.Value
};
}
}
Sample project:
Hi,
I managed to find a workaround for this issue. We can create a rule for ignoring member using .IgnoreMember().
As this is type specific, we have to use a .NewConfig<>() for desired mapping configuration.
Example:
config.NewConfig<Src, Dst>()
.IgnoreHiddenAndReadOnlyProperties()
.GenerateMapper(MapType.Map);
IgnoreHiddenAndReadOnlyProperties() extension method definition:
public static TypeAdapterSetter<TSource, TDestination> IgnoreHiddenAndReadOnlyProperties<TSource, TDestination>(
this TypeAdapterSetter<TSource, TDestination> config) =>
config.IgnoreMember((m, s) =>
{
if (m.Info is not PropertyInfo pi) return true;
var isDestination = s == MemberSide.Destination;
return IsPropertyHidden(pi, isDestination ? typeof(TDestination) : typeof(TSource))
|| (isDestination && !IsPropertyWritable(pi));
});
public static bool IsPropertyWritable(this PropertyInfo pi) =>
pi is { CanWrite: true } && pi.GetSetMethod() is { IsPublic: true };
public static bool IsPropertyHidden(this PropertyInfo pi, Type dstType)
{
var e = dstType.GetProperty(pi.Name,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
return e is not null && pi.DeclaringType != e.DeclaringType;
}
Is not perfect as it does not work with .TwoWays() - you'll have to manually add configuration for reverse mapping.
Thanks @rafalka, I'm leaving this open in case anyone else has similar problems or if anyone has suggestions on how to improve this. Feel free to open a PR to add this extension method to the main code base.