Collection is empty after mapping elements to an existing collection if existing target instance is returned by the resolver #4170
-
Source/destination types public class SourceType
{
public SourceType(List<string> list) => Strings = list;
public List<string> Strings { get; set; }
}
public class TargetType
{
public TargetType(List<string> list) => Strings = list;
public List<string> Strings { get; set; }
} Mapping configuration var conf = new MapperConfiguration(conf =>
conf.CreateMap<SourceType, TargetType>()
.ForMember(
t => t.Strings, opt => opt.MapFrom(
(src, tgt, obj) => { obj.AddRange(src.Strings); return obj; })
)); For reference, configuration working as expected: var conf = new MapperConfiguration(conf =>
conf.CreateMap<SourceType, TargetType>()
.ForMember(
t => t.Strings, opt => opt.MapFrom(
(src, tgt, obj) => { obj.AddRange(src.Strings); return obj.ToList(); }) //Passes
)); Version: 12.0.1-alpha.0.2, 12.0.0, 11.0.1Expected behaviorWhen mapping elements from a source collection to a target collection, the target collection should contain any elements returned in the MapFrom. Actual behaviorTarget collections becomes null or empty if the same instance is returned by the resolver. Works as expected if a shallow copy is returned instead. Steps to reproduceComplete NUnit test below. Test1 fails, Test2 passes, difference being a .ToList() in Test2's MapFrom. using NUnit.Framework;
using AutoMapper;
using System.Collections.Generic;
using System.Linq;
namespace MapToCollection;
public class MapToCollectionTests
{
public class SourceType
{
public SourceType(List<string> list) => Strings = list;
public List<string> Strings { get; set; }
}
public class TargetType
{
public TargetType(List<string> list) => Strings = list;
public List<string> Strings { get; set; }
}
[SetUp]
public void Setup()
{
}
[Test]
public void Test1()
{
var conf = new MapperConfiguration(conf =>
conf.CreateMap<SourceType, TargetType>()
.ForMember(
t => t.Strings, opt => opt.MapFrom(
(src, tgt, obj) => { obj.AddRange(src.Strings); return obj; }) //Fails, tgt.Strings become empty
));
var mapper = conf.CreateMapper();
var src = new SourceType(new() { "one", "two" });
var tgt = new TargetType(new() { "three", "four" });
mapper.Map(src, tgt);
Assert.NotNull(tgt.Strings);
Assert.Contains("one", tgt.Strings);
Assert.Contains("two", tgt.Strings);
Assert.Contains("three", tgt.Strings);
Assert.Contains("four", tgt.Strings);
}
[Test]
public void Test2()
{
var conf = new MapperConfiguration(conf =>
conf.CreateMap<SourceType, TargetType>()
.ForMember(
t => t.Strings, opt => opt.MapFrom(
(src, tgt, obj) => { obj.AddRange(src.Strings); return obj.ToList(); }) //Passes
));
var mapper = conf.CreateMapper();
var src = new SourceType(new() { "one", "two" });
var tgt = new TargetType(new() { "three", "four" });
mapper.Map(src, tgt);
Assert.NotNull(tgt.Strings);
Assert.Contains("one", tgt.Strings);
Assert.Contains("two", tgt.Strings);
Assert.Contains("three", tgt.Strings);
Assert.Contains("four", tgt.Strings);
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
I think this is better suited for StackOverflow. |
Beta Was this translation helpful? Give feedback.
I think this is better suited for StackOverflow.