2016-07-26 90 views
2

在AutoMapper 5.0.2下:爲什麼AutoMapper在屬性是接口類型時嘗試映射null屬性?

當源對象具有接口類型屬性時,即使屬性爲null,爲該接口類型定義的映射也將被完全評估。如果映射使用ResolveUsing,這是有問題的,因爲它可能不會期望null並可能拋出。

下面的測試夾具使用相當人爲的映射來強調該問題。一個測試通過,則其他失敗:

[TestFixture] 
public class NullPropertyTests 
{ 
    public class ChildClass : IChildInterface 
    { 
     public string OtherValue { get; set; } 
     public string Value { get; set; } 
    } 

    public interface IChildInterface 
    { 
     string Value { get; set; } 
    } 

    public class ClassReferencesChildClass 
    { 
     public ChildClass Child { get; set; } 
    } 

    public class ClassReferencesChildInterface 
    { 
     public IChildInterface Child { get; set; } 
    } 

    public class DtoClass 
    { 
     public DtoChildClass Child { get; set; } 
    } 

    public class DtoChildClass 
    { 
     public string OtherValue { get; set; } 
     public string Value { get; set; } 
    } 

    [Test] 
    public void BreakingTest() 
    { 
     var mapper = CreateAndValidateMapper(e => 
     { 
      e.CreateMap<ClassReferencesChildInterface, DtoClass>(); 

      e.CreateMap<IChildInterface, DtoChildClass>() 
       .Include<ChildClass, DtoChildClass>() 
       .ForMember(d => d.Value, x => x.ResolveUsing(c => DoStuff(c.Value?.Split(' ')))) 
       .ForMember(d => d.OtherValue, x => x.Ignore()); 
      e.CreateMap<ChildClass, DtoChildClass>(); 
     }); 

     // This fails due to a NullReferenceException: 
     mapper.Map<DtoClass>(new ClassReferencesChildInterface { Child = null }); 
    } 

    [Test] 
    public void PassingTest() 
    { 
     var mapper = CreateAndValidateMapper(e => 
     { 
      e.CreateMap<ClassReferencesChildClass, DtoClass>(); 

      e.CreateMap<IChildInterface, DtoChildClass>() 
       .Include<ChildClass, DtoChildClass>() 
       .ForMember(d => d.Value, x => x.ResolveUsing(c => DoStuff(c.Value?.Split(' ')))) 
       .ForMember(d => d.OtherValue, x => x.Ignore()); 
      e.CreateMap<ChildClass, DtoChildClass>(); 
     }); 

     mapper.Map<DtoClass>(new ClassReferencesChildClass { Child = null }); 
    } 

    private static string DoStuff(string[] value) 
    { 
     return value.FirstOrDefault(); 
    } 

    private static IMapper CreateAndValidateMapper(Action<IMapperConfigurationExpression> configure) 
    { 
     var configuration = new MapperConfiguration(configure); 
     configuration.AssertConfigurationIsValid(); 
     return configuration.CreateMapper(); 
    } 
} 

在AutoMapper 3.2.1(與類型等根據需要調整爲編譯)兩個測試將通過。

我們可以修改幾十個映射來明確容忍空值,但對於以前工作得很好的東西來說,似乎過於冗長。

這是預期的行爲?有沒有一種解決方法,它不需要重複大量的映射?

回答