在AutoMapper 5.0.2下:
当源对象具有interface-typed属性时,即使该属性为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下(根据编译需要调整类型等),两个测试都将通过。
我们可以修改几十个映射来明确地容忍空值,但对于以前工作得很好的东西来说,这似乎过于冗长。
这是预期的行为吗?是否有一个解决方法,它不需要重复大量的映射?