如果属性是接口类型,为什么AutoMapper会尝试映射null属性?

时间:2016-07-26 16:02:06

标签: .net automapper

在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下(根据编译需要调整类型等),两个测试都将通过。

我们可以修改几十个映射来明确地容忍空值,但对于以前工作得很好的东西来说,这似乎过于冗长。

这是预期的行为吗?是否有一个解决方法,它不需要重复大量的映射?

1 个答案:

答案 0 :(得分:1)

我提出了issue with the Automapper project。它似乎是固定的,修复程序将在5.1.0中出现。