Automapper: ForMember 中的复杂 if else 语句

42

假设 Date 是一个可空的 DateTime

Mapper.CreateMap<SomeViewModels, SomeDTO>()               
             .ForMember(dest => dest.Date,
                        opt => opt.MapFrom(src =>
                        {
                            DateTime? finalDate = null;
                            if (src.HasDate == "N")
                            {
                                // so it should be null
                            }
                            else
                            {                                   
                                endResult = DateTime.Parse(src.Date.ToString());
                                
                            }                               
                            return finalDate;

                        }));

我得到的错误是:

错误 30:带有语句体的 Lambda 表达式不能转换为表达式树。

当然,我完全意识到我可以简化查询,比如:

Mapper.CreateMap<SomeViewModels, SomeDTO>()
             .ForMember(dest => dest.Date,
                        opt => opt.MapFrom(src => src.HasDate == "N" ? null : DateTime.Parse(src.Date.ToString())));
    

但是如果我坚持保留第一个例子的结构,因为我有更复杂的if else语句,第二个例子将无法满足,或者至少不容易阅读?

3个回答

80
在最新版本的AutoMapper中,ResolveUsing已被移除。替代方案是使用MapFrom的一个新重载。
void MapFrom<TResult>(Func<TSource, TDestination, TResult> mappingFunction);

只需添加另一个 lambda/函数参数,就会调用此新重载版本:

        CreateMap<TSource, TDest>()
                .ForMember(dest => dest.SomeDestProp, opt => opt.MapFrom((src, dest) =>
                {
                    TSomeDestProp destinationValue;

                    // mapping logic goes here

                    return destinationValue;
                }));

8
谢谢,这很有帮助,因为ResolveUsing已被删除! - Tempuslight
2
这太完美了,谢谢。我不知道为什么所有这些示例在AutoMapper官方网站上都不可用或难以找到。 - Garry
4
大家好。在大多数情况下,我建议删除AutoMapper并编写手写映射代码,或者更好的是找到一种避免首次复制值的方法。谢谢。 - Ronnie Overby

30
使用 ResolveUsing 方法:
Mapper.CreateMap<SomeViewModels, SomeDTO>()               
         .ForMember(dest => dest.Date, o => o.ResolveUsing(Converter));

private static object Converter(SomeViewModels value)
{
    DateTime? finalDate = null;
    if (value.Date.HasDate == "N")
    {
        // so it should be null
    }
    else
    {                                   
        finalDate = DateTime.Parse(value.Date.ToString());
    }                               
    return finalDate;
}

以下是更多信息:AutoMapper:MapFrom与ResolveUsing


那么,即使其余的映射是直接的,我还是需要在转换器中定义其他属性的映射吗? - Sum NL
简而言之,是的。但是你可以使用Automapper映射器忽略此属性并手动设置它:) 你的Date属性是什么类型? - Backs
这是一个可空的DateTime,我在问题中忘记了提及。 你能把那个例子(在转换器中使用automapper映射)也加到你的答案里吗?谢谢。 - Sum NL
@Sum 我完全错了 :) 你可以使用ResolveUsing选项与方法一起使用!这样更容易! - Backs
1
@Sum 这里之所以出错是因为 MapFrom 函数期望传入一个 Lambda 表达式,但你却传入了一个 Lambda 语句(带有花括号的)。 - Jimmy Bogard
显示剩余2条评论

0

试着这样做

Mapper.CreateMap<SomeViewModels, SomeDTO>()               
         .ForMember(dest => dest.Date,
                    opt => opt.MapFrom(src => src.HasDate == "N" ? "" : DateTime.Parse(src.Date.ToString())));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接