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

.net 如果属性是接口类型,为什么AutoMapper会尝试映射null属性?,.net,automapper,.net,Automapper,在AutoMapper 5.0.2下: 当源对象具有接口类型的属性时,即使该属性为null,也将完全计算为该接口类型定义的映射。如果映射使用ResolveUsing,则会出现问题,因为它可能不需要null,并且可能会抛出 下面的测试夹具使用一个相当人为的映射来突出问题。一个测试通过,另一个测试失败: [TestFixture] public class NullPropertyTests { public class ChildClass : IChildInterface {

在AutoMapper 5.0.2下:

当源对象具有接口类型的属性时,即使该属性为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();
    }
}
[TestFixture]
公共类NullPropertyTests
{
公共类子类:IchilInterface
{
公共字符串OtherValue{get;set;}
公共字符串值{get;set;}
}
公共接口IchilInterface
{
字符串值{get;set;}
}
公共类ClassReferencesChildClass
{
公共子类子{get;set;}
}
公共类ClassReferencesChildInterface
{
公共i接口子项{get;set;}
}
公共类DTO类
{
公共DtoChildClass子级{get;set;}
}
公共类DtoChildClass
{
公共字符串OtherValue{get;set;}
公共字符串值{get;set;}
}
[测试]
公共破空测试()
{
变量映射器=CreateAndValidateMapper(e=>
{
e、 CreateMap();
e、 CreateMap()
.包括()
.ForMember(d=>d.Value,x=>x.ResolveUsing(c=>DoStuff(c.Value?.Split(“”)))
.ForMember(d=>d.OtherValue,x=>x.Ignore());
e、 CreateMap();
});
//由于NullReferenceException,此操作失败:
Map(新的ClassReferencesChildInterface{Child=null});
}
[测试]
public void PassingTest()
{
变量映射器=CreateAndValidateMapper(e=>
{
e、 CreateMap();
e、 CreateMap()
.包括()
.ForMember(d=>d.Value,x=>x.ResolveUsing(c=>DoStuff(c.Value?.Split(“”)))
.ForMember(d=>d.OtherValue,x=>x.Ignore());
e、 CreateMap();
});
Map(新的ClassReferencesChildClass{Child=null});
}
私有静态字符串DoStuff(字符串[]值)
{
返回值.FirstOrDefault();
}
专用静态IMapper CreateAndValidateMapper(操作配置)
{
var配置=新的MapperConfiguration(配置);
assertConfigurationsValid();
返回configuration.CreateMapper();
}
}
根据AutoMapper 3.2.1(根据编译需要调整类型等),两个测试都将通过

我们可以修改几十个映射来显式地容忍空值,但对于以前工作正常的东西来说,这似乎过于冗长了

这是故意的行为吗?是否有一种不需要复制大量映射的解决方法?

我提出了这个问题。它似乎已被修复,修复程序将在5.1.0中发布