Automapper条件映射来自多个源字段

5
我可以帮您进行翻译。以下是需要翻译的内容:

我有一个源代码类,如下所示:

public class Source
{
    public Field[] Fields { get; set; }
    public Result[] Results { get; set; }
}

并且有一个目标类,例如:

public class Destination
{
    public Value[] Values { get; set; }
}

我希望能够根据哪一个值不为空(只有一个值会有值),从FieldsResults中映射到Values

我尝试了以下映射:

CreateMap<Fields, Values>();                
CreateMap<Results, Values>();                

CreateMap<Source, Destination>()                
            .ForMember(d => d.Values, opt =>
            {
                opt.PreCondition(s => s.Fields != null);
                opt.MapFrom(s => s.Fields });
            })
            .ForMember(d => d.Values, opt =>
            {
                opt.PreCondition(s => s.Results != null);
                opt.MapFrom(s => s.Results);
            });

唯一的问题是,如果最后一个 .ForMember 映射不符合条件,则会清除第一个映射的结果。

我也考虑过使用条件运算符:

opt => opt.MapFrom(s => s.Fields != null ? s.Fields : s.Results)

但很明显它们是不同的类型,所以无法编译。

如何根据条件从不同类型的源属性映射到单个属性?

谢谢

3个回答

7

有一个ResolveUsing()方法,允许您进行更复杂的绑定,并且可以使用IValueResolverFunc。就像这样:

CreateMap<Source, Destination>()
    .ForMember(dest => dest.Values, mo => mo.ResolveUsing<ConditionalSourceValueResolver>());

根据您的需求,价值解析器可能如下所示:

 public class ConditionalSourceValueResolver : IValueResolver<Source, Destination, Value[]>
    {
        public Value[] Resolve(Source source, Destination destination, Value[] destMember, ResolutionContext context)
        {
            if (source.Fields == null)
                return context.Mapper.Map<Value[]>(source.Results);
            else
                return context.Mapper.Map<Value[]>(source.Fields);
        }
    }

太好了,成功了,谢谢!我认为我的问题之一是在离开映射器的静态版本后,我不确定如何在另一个映射器内部实际执行映射。现在我知道可以从上下文中获取它。谢谢! - ADringer
令人沮丧的是,当你发现自己几乎在每个映射中都使用ResolveUsing时,会导致一些丑陋的代码,并让你想知道是否使用AutoMapper比构建工厂更好。 - crush

3

参考@animalito_maquina的回答:链接

以下是关于8.0版本升级的更新:

CreateMap<Source, Destination>()
    .ForMember(dest => dest.Values, mo => mo.MapFrom<ConditionalSourceValueResolver>());

为了节省您的时间,对于可查询扩展不支持使用ValueResolvers。


2

ResolveUsing不可用,尝试使用以下方法。 对我起作用了。

CreateMap<Source, Destination>()   
.ForMember(opt => opt.value, map => 
map.MapFrom((s, Ariel) => s.Fields != null ? s.Fields : s.Results));

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