2

使用 AutoMapper:映射嵌套集合时,我希望任何未映射的属性都保留其原始值。相反,它们被设置为空。

示例:
我有这四个类
(注意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...。我希望这是任何未映射属性的默认行为。

Test1Child当我直接从to映射时Test2Child,它工作正常;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>to 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.

我该如何解决?

4

3 回答 3

2

正如@MightyMuke's answer的评论中提到的那样,@PatrickSteele 在这里提出了一个很好的观点:自动将每个项目从源列表映射到目标列表可能没有意义......即“但是如果一个列表有 3另一个列表有 5 个?

就我而言,我知道源列表和目标列表将始终具有相同的长度,并且(重要的是)源列表中的第 N 项始终与目标列表中的第 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]);
        });
于 2013-01-09T08:42:04.003 回答
0

尝试UseDestinationValue按照这个类似问题的答案中的描述使用: Automapper overwrites missing source property on list with child objects

于 2013-01-09T07:57:42.967 回答
0

我遇到了同样的问题。基本上,自动映射器不知道列表对象中的键是什么,以便将它们与原始对象匹配,因此它会新建一个对象。如果您希望属性保留,您需要帮助它了解如何匹配回您的原始项目,以便您可以映射更改。为了做到这一点,你需要有一个你现在没有的钥匙。

尝试以下操作:

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");
于 2013-01-14T21:09:30.237 回答