自动映射 - 映射重写属性会导致转换异常

时间:2017-06-06 20:39:22

标签: c# automapper

我们刚刚从Automapper 3.3.0升级到6.0.2,在升级我们的解决方案之后,其中一个映射似乎不再起作用了。

考虑一下:

public class Source{
   public Decimal GrossAmount {get;set;}
}

public class DerivedSource : Source{
}

public class DestinationMaster{
   public virtual DestinationChild Child {get;set;}
}

public class DestinationChild{
   public decimal GrossAmount {get;set;}
}

public class DerivedDestinationMaster : DestinationMaster {
   private DerivedDestinationChild _destinationChild;

   public override DestinationChild Child {
      get{return _destinationChild;}
      set{_destinationChild = (DerivedDestinationChild)value;}
   }
}

public class DerivedDestinationChild : DestinationChild{
  public string OtherProperty {get;set;}
}

现在为映射:

CreateMap<Source,DestinationMaster>()
  .Include<DerivedSource,DerivedDestinationMaster>();

CreateMap<DerivedSource,DerivedDestinationMaster>()
  .ForMember(dest => dest.Child, act=> act.MapFrom(src => new DerivedDestinationChild(){ GrossAmount = src.GrossAmount }));

现在,如果我尝试将“Source”对象映射到新的“DerivedDestinationMaster”实例,我会得到一个Exception,告诉我无法将“DestinationChild”转换为“DerivedDestinationChild”。

如果我在overriden属性的“setter”访问器中放置一个断点,我清楚地看到传递的实例是“DestinationChild”类型。我还可以看到“DestinactionChild”类有两个构造函数调用。 “GrossAmount”值是来自“Source”对象的好值而不是0,就好像在创建“DerivedDestinationChild”实例之后,它创建了一个新的“DestinationChild”实例来接收信息并自动化这两个对象。

我们的场景有点复杂(我们使用IValueResolver),但我们使用“MapFrom”,“UseValue”和自定义解析器进行测试,并且在所有情况下,最终实例都不是派生类型。

如果我们在映射上放置“act.Ignore()”,则不会引发异常

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

作为文档here,映射遵循继承树的特定顺序。你可以通过复制一些地图来实现它的工作方式,这对你来说是一个可行的解决方案吗?

class Program
{
    static void Main(string[] args)
    {
        Mapper.Initialize(cfg =>
        {
            cfg.CreateMap<Source, DestinationMaster>().ForMember(dest => dest.Child, act => act.MapFrom(s => new DestinationChild { GrossAmount = s.GrossAmount}));
            cfg.CreateMap<DerivedSource, DerivedDestinationMaster>().IncludeBase<Source, DestinationMaster>().ForMember(dest => dest.Child, act => act.MapFrom(s => new DerivedDestinationChild { GrossAmount = s.GrossAmount }));
        });

        var source = new Source() {GrossAmount = 99};
        var destinationMaster = Mapper.Map<DestinationMaster>(source);
        Debug.Assert(destinationMaster.Child.GrossAmount == source.GrossAmount);
        Debug.Assert(destinationMaster.Child.GetType() == typeof(DestinationChild));

        var derivedSource = new DerivedSource() {GrossAmount = 10};
        var derivedDestinationMaster = Mapper.Map<DerivedDestinationMaster>(derivedSource);
        Debug.Assert(derivedDestinationMaster.Child.GrossAmount == derivedSource.GrossAmount);
        Debug.Assert(derivedDestinationMaster.Child.GetType() == typeof(DerivedDestinationChild));
    }
}

除此之外,我不确定如何使用从基本映射映射的GrossAmount返回特定的派生类型。

相关问题