AutoMapper:映射子集合1至儿童Collection2时丢失未映射属性值(AutoMappe

2019-10-17 14:00发布

使用AutoMapper:当映射嵌套集合,我希望任何未映射的属性都保留了其原始值。 取而代之的是,他们被设置为null。

例:
我有这四类
(注意Test2ChildName属性,而Test1Child没有):

public class Test1
{
    public List<Test1Child> Children { get; set; }
}
public class Test2
{
    public List<Test2Child> Children { get; set; }
}
public class Test1Child
{
    public int Value { get; set; }
}
public class Test2Child
{
    public string Name { get; set; }
    public int Value { get; set; }
}

...和一个简单的映射设置。

Mapper.CreateMap<Test1, Test2>();
Mapper.CreateMap<Test1Child, Test2Child>().ForMember(m => m.Name, o => o.Ignore());
Mapper.AssertConfigurationIsValid();    // Ok

我想原值Test2Child.Name映射过程中要保留....我希望这是对任何未映射属性的默认行为。

当我直接从地图Test1ChildTest2Child ,它工作正常; Value映射和Name被保留:

var a = new Test1Child {Value = 123};
var b = new Test2Child {Name = "fred", Value = 456};
Mapper.Map(a, b);
Assert.AreEqual(b.Value, 123);    // Ok
Assert.AreEqual(b.Name, "fred");  // Ok

当映射为嵌套集合( List<Test1Child>List<Test2Child>
Value正确映射...... 但对于原始值Name丢失!

var c = new Test1 { Children = new List<Test1Child> { new Test1Child { Value = 123 } } };
var d = new Test2 { Children = new List<Test2Child> { new Test2Child { Name = "fred", Value = 456 } } };
Mapper.Map(c, d);
Assert.AreEqual(d.Children[0].Value, 123);    // Ok
Assert.AreEqual(d.Children[0].Name, "fred");  // FAILS! Name is null.

我该如何解决?

Answer 1:

正如@ MightyMuke的答案的评论提到,@PatrickSteele使得一个好点这里 :也许它没有任何意义,以从源列表中的每个项目自动映射到目标列表....即“ 但是,如果一个列表中有3什么和其他列表中有5? “

以我为例,我知道源和目标列表将始终具有相同的长度,并在源列表(重要)的第N项总是直接对应于DEST列表中的第N项。

所以,这个工作,但我不觉得自己还不错....

Mapper.CreateMap<Test1, Test2>()
    .ForMember(m => m.Children, o => o.Ignore())
    .AfterMap((src, dest) =>
        {
            for (var i = 0; i < dest.Children.Count; i++)
                Mapper.Map(src.Children[i], dest.Children[i]);
        });


Answer 2:

尝试使用UseDestinationValue在回答这个类似的问题描述: Automapper覆盖与子对象列表中缺少源属性



Answer 3:

我遇到了同样的问题。 基本上automapper不知道什么键(一个或多个)您的列表对象,以便与原来的配合他们,所以它要新建立一个对象。 如果你想要的属性保留,你需要帮助它了解如何搭配回原来的项目,以便你可以映射的变化。 为了做到这一点,你需要有钥匙,你没有现在。

尝试类似如下:

public class Test1
{
    public List<Test1Child> Children { get; set; }
}
public class Test2
{
    public List<Test2Child> Children { get; set; }
}
public class Test1Child
{
    public int ChildId { get; set; }
    public int Value { get; set; }
}
public class Test2Child
{
    public int ChildId { get; set; }
    public string Name { get; set; }
    public int Value { get; set; }

    public Test2Child() 
    { }

    public Test2Child(int childId)
    {
        // of course you will need to load this from your data source, but for testing.  :)
        if (childId == 1)
        {
            ChildId = 1;
            Name = "fred";
            Value = 456;
        }
    }
}

Mapper.CreateMap<Test1, Test2>();
Mapper.CreateMap<Test1Child, Test2Child>()
    .ConstructUsing(t => t.ChildId > 0 ? new Child(t.ChildId) : new Child())
    .ForMember(m => m.Name, o => o.Ignore());

Mapper.AssertConfigurationIsValid();

var c = new Test1 { Children = new List<Test1Child> { new Test1Child { ChildId = 1, Value = 123 } } };
var d = new Test2 { Children = new List<Test2Child> { new Test2Child { ChildId = 1, Name = "fred", Value = 456 } } };
Mapper.Map(c, d);
Assert.AreEqual(d.Children[0].Value, 123);
Assert.AreEqual(d.Children[0].Name, "fred");


文章来源: AutoMapper: Losing unmapped property values when mapping Child Collection 1 to Child Collection2