如何使用AutoMapper正确配置`int?`到`int`投影?

时间:2016-10-12 06:42:55

标签: c# automapper

我在使这个工作正常时遇到了一些麻烦。我有两个班:

public class TestClassA
{
    public int? NullableIntProperty { get; set; }
}

public class TestClassB
{
    public int NotNullableIntProperty { get; set; }
}

然后我设置了以下映射:

cfg.CreateMap<TestClassA, TestClassB>()
    .ForMember(dest => dest.NotNullableIntProperty,
               opt => opt.MapFrom(src => src.NullableIntProperty));

cfg.CreateMap<TestClassA, TestClassA>()
    .ForMember(dest => dest.NullableIntProperty,
               opt => opt.MapFrom(src => src.NullableIntProperty));

cfg.CreateMap<TestClassB, TestClassA>()
    .ForMember(dest => dest.NullableIntProperty,
               opt => opt.MapFrom(src => src.NotNullableIntProperty));

cfg.CreateMap<TestClassB, TestClassB>()
    .ForMember(dest => dest.NotNullableIntProperty,
               opt => opt.MapFrom(src => src.NotNullableIntProperty));

我现在已经设置了四个映射,并将测试以下场景:

int? => int
int => int?
int => int
int? => int?

在测试类中,我然后使用这样的映射:

var testQueryableDest = testQueryableSrc.ProjectTo<...>(_mapper.ConfigurationProvider);

我期望在此阶段不能工作的唯一预测是TestClassA => TestClassB,因为我可以看到在价值为{{的情况下,AutoMapper可能不知道如何处理int? 1}}。果然,情况确实如此。所以我设置了null的映射,如下所示:

int? => int

这就是事情变得奇怪的地方。只要我添加此映射,cfg.CreateMap<int?, int>() .ProjectUsing(src => src ?? default(int)); 的映射就无法创建。它给出了以下错误消息:

  

表达类型&#39; System.Int32&#39;不能用于分配类型&#39; System.Nullable`1 [System.Int32]&#39;

我发现此消息非常奇怪,因为TestClassB => TestClassB根本没有TestClassB。那么这里发生了什么?我觉得我必须误解一下AutoMapper如何处理这些预测。我意识到各种代码可能很难拼凑起来,所以这里是整个测试类的参考:

int?

1 个答案:

答案 0 :(得分:3)

我发现重现这种情况的最短路径如下:

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<int?, int>().ProjectUsing(x => x ?? default(int));
    cfg.CreateMap<TestClassA, TestClassA>()
        .ForMember(a => a.NullableIntPropety, o => o.MapFrom(a => a.NullableIntProperty));
}

在我看来,AutoMapper试图在这里使用int? => int映射器,尽管在这里可以使用更明显的基于身份的映射。

由于每个int也是有效的int?,因此AutoMapper 尝试在此处使用int? => int映射器并将结果分配给int?会员。但是,当解决这个任务时,似乎有些东西不能正常工作,因此也是例外。

似乎可以解决的问题是添加另一个映射,int? => int?的身份映射:

cfg.CreateMap<int?, int?>().ProjectUsing(x => x);

然后,正在使用此映射而不会发生异常(并且映射也适用于所有示例)。

此问题似乎存在于当前的AutoMapper 5.1.x版本中(当前为5.1.1)。好消息是,它已经被修复了。如果你从myget feed尝试当前的5.2 alpha,那么代码可以正常运行而没有任何问题。

自5.1.1发布以来,代码库已经看到了很多关于可空映射的多个修复的贡献(例如thisthis拉取请求)。我认为其中一个变化已经解决了这个问题。

最有可能的是,拉取请求#1672只是意味着删除不需要的代码,但显然也修复了issue 1664,这是关于AutoMapper显然优先考虑可空的源映射而不是非可空来源即使非正在映射可空来源。这听起来非常像你遇到的这个问题。

因此,现在,您可以添加上述解决方法以将类型映射到自身或使​​用alpha版本,同时我们等待5.2发布。