【问题标题】:AutoMapper Map properties of nested objects if Not Null如果不是 Null,则 AutoMapper 映射嵌套对象的属性
【发布时间】:2012-07-19 19:46:32
【问题描述】:

我有以下示例对象..

  public class ComplexObject
  {
    public string Name { get; set; }
    public SimpleObject Child1 { get; set; }
    public SimpleObject Child2 { get; set; }
  }
  public class SimpleObject : IEquatable< SimpleObject >
  {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Gender { get; set; }
    public int? Age { get; set; }
  }

使用以下 AutoMapper 配置

  Mapper.CreateMap<SimpleObject, SimpleObject>()
    .ForAllMembers(expression=>expression.Condition(r=>!r.IsSourceValueNull));

  Mapper.CreateMap<ComplexObject, ComplexObject>()
    .ForAllMembers(expression=>expression.Condition(resolutionContext=>!resolutionContext.IsSourceValueNull));

以及下面的 NUnit 测试...

[SetUp] public void Should_run_before_each_test()
{
  child1 = new SimpleObject { FirstName = "Tom", LastName = "Smith", Age = 34, Gender = "Male" };
  child2 = new SimpleObject { FirstName = "Andy", LastName = "Smith-bob", Age = 21, Gender = "Male" };
}

[ Test ]
public void Should_ignore_null_properties_in_nested_objects()
{
  var source = new ComplexObject()
  {
    Name = "blue",
    Child1 = new SimpleObject{FirstName = "dot", LastName = "net"}
  };
  var destination = new ComplexObject()
  {
    Name = "Andy",
    Child1 = child1,
    Child2 = child2
  };

  destination = Mapper.Map(source, destination);

  destination.Name.Should(Be.EqualTo(source.Name));
  destination.Child1.FirstName.Should(Be.EqualTo("dot"));
  destination.Child1.LastName.Should(Be.EqualTo("net")  );
  destination.Child1.Age.Should(Be.EqualTo(child1.Age)  );
  destination.Child1.Gender.Should(Be.EqualTo(child1.Gender)  );
}

在断言年龄时上述测试失败,因为 AutoMapper 正在将 null 推送到目标对象。

我是否对 AutoMapper 期望过高,或者我错过了一些重要的地图配置步骤。

最终目标是通过 MVC 操作将一个非常复杂的域对象绑定到传入的表单数据。然后,AutoMapper 将用于仅将非空属性(在对象图的所有深度)合并到整个多步骤表单中维护的真实实例中。

以防万一有人需要知道...我还尝试了以下映射配置,但没有任何运气:(

  Mapper.CreateMap<ComplexObject, ComplexObject>()
    .ForMember(x=>x.Child1, l=>l.ResolveUsing(x=>x.Child1 == null?null:Mapper.Map<SimpleObject,SimpleObject>(x.Child1)))
    .ForMember(x=>x.Child2, l=>l.ResolveUsing(x=>x.Child2 == null?null:Mapper.Map<SimpleObject,SimpleObject>(x.Child2)))
    .ForAllMembers(expression=>expression.Condition(resolutionContext=>!resolutionContext.IsSourceValueNull));

【问题讨论】:

    标签: c# automapper automapper-2


    【解决方案1】:

    如果源值为 null,为什么您期望目标对象上的值不为 null? int? 的默认值为null,因此,当您调用时

    destination.Child1.Age.Should(Be.EqualTo(child1.Age));

    .Should 失败了。这应该是预期的行为。

    尝试Assert.Null(detination.Child1.Age) 之类的方法,应该可以通过。 AutoMapper 不会“推送”该值,没有源值,因此,Age 将拥有它的默认值。

    【讨论】:

    • nope.. 不是当我试图说服 AutoMapper 按照下面的尝试映射忽略空源值时.. Mapper.CreateMap&lt;SimpleObject, SimpleObject&gt;() .ForAllMembers(expression=&gt;expression.Condition(r=&gt;!r.IsSourceValueNull));
    • 你能添加你分配给child1child2的内容吗?
    • 问题在于,在您的示例中,它不是将SimpleObject 映射到SimpleObject,而是将ComplexObject 映射到ComplexObject。因为source.Child1 不为空,它只是将它分配给destination.Child1
    • 是的..我也做到了这一点......我假设 AutoMapper 将/应该处理更深层次的类型映射......
    • 来自这个问题:stackoverflow.com/questions/2463183/… 看起来 ValueInjector 项目可以完全满足您的需求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-20
    • 1970-01-01
    • 2016-03-20
    • 2020-04-03
    • 2022-01-06
    • 1970-01-01
    • 2012-02-25
    相关资源
    最近更新 更多