Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions src/Mapster.Tests/WhenMappingGetterOnlyMapToTargetRegression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using MapsterMapper;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shouldly;

namespace Mapster.Tests;

/// <summary>
/// https://github.com/MapsterMapper/Mapster/issues/900
/// </summary>
[TestClass]
public class WhenMappingGetterOnlyMapToTargetRegression
{
[TestMethod]
public void MapToTarget_WithCustomMap_ShouldReplaceExistingDestinationMemberValue()
{
var config = new TypeAdapterConfig();
config.NewConfig<Dto900, Entity900>()
.Map(x => x.Data, x => x.Data == null ? null : new Data900(x.Data.Value));

var mapper = new Mapper(config);

var dto = new Dto900 { Data = new Data900("new") };
var entity = mapper.Map(dto, new Entity900 { Data = new Data900("old") });

entity.Data.ShouldNotBeNull();
entity.Data!.Value.ShouldBe("new");
}

[TestMethod]
public void MapToTarget_WithCustomMap_ShouldStillWorkWhenDestinationMemberIsNull()
{
var config = new TypeAdapterConfig();
config.NewConfig<Dto900, Entity900>()
.Map(x => x.Data, x => x.Data == null ? null : new Data900(x.Data.Value));

var mapper = new Mapper(config);

var dto = new Dto900 { Data = new Data900("new") };
var entity = mapper.Map(dto, new Entity900());

entity.Data.ShouldNotBeNull();
entity.Data!.Value.ShouldBe("new");
}

[TestMethod]
public void Map_WithCustomMap_ShouldStillWorkForNewDestination()
{
var config = new TypeAdapterConfig();
config.NewConfig<Dto900, Entity900>()
.Map(x => x.Data, x => x.Data == null ? null : new Data900(x.Data.Value));

var mapper = new Mapper(config);

var dto = new Dto900 { Data = new Data900("new") };
var entity = mapper.Map<Entity900>(dto);

entity.Data.ShouldNotBeNull();
entity.Data!.Value.ShouldBe("new");
}

private class Dto900
{
public Data900? Data { get; set; }
}

private class Entity900
{
public Data900? Data { get; set; }
}

private class Data900(string value)
{
public string Value => value;
}
}
7 changes: 7 additions & 0 deletions src/Mapster/Adapters/BaseClassAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,13 @@ protected static bool IsCanUsingDestinationValue(CompileArgument arg, IMemberMod
return false;
}

protected static bool HasCustomMemberMap(CompileArgument arg, IMemberModel destinationMember)
{
return arg.Settings.Resolvers.Any(resolver =>
!resolver.IsChildPath &&
string.Equals(resolver.DestinationMemberName, destinationMember.Name, StringComparison.InvariantCultureIgnoreCase));
}

protected static bool ProcessIgnores(
CompileArgument arg,
IMemberModel destinationMember,
Expand Down
3 changes: 2 additions & 1 deletion src/Mapster/Adapters/ClassAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ protected override Expression CreateBlockExpression(Expression source, Expressio
Dictionary<LambdaExpression, Tuple<List<Expression>, Expression>>? conditions = null;
foreach (var member in members)
{
var destMember = arg.MapType == MapType.MapToTarget || member.UseDestinationValue
var hasCustomMap = HasCustomMemberMap(arg, member.DestinationMember);
var destMember = (arg.MapType == MapType.MapToTarget || member.UseDestinationValue) && !hasCustomMap
? member.DestinationMember.GetExpression(destination)
: null;

Expand Down