32

这是我的代码:

Mapper.CreateMap<Foo, Foo2>()
   .ForMember(dest => dest.Bar, opt => opt.MapFrom(src => src.Bar == null ? new BarViewModel() : src.Bar))

基本上,“BarViewModel”有一个无参数的 ctor,它在类中设置属性。

所以我想对 AutoMapper 说:

如果值为 null,则使用该类的 ctor。否则使用您现有的映射

以上是给我一个 C# 编译器错误。而且我猜演员也行不通。

那么有没有一个 AutoMapper 技巧来做到这一点?

最坏的情况是我可以删除该属性的映射,然后执行以下操作:

var mapped = Mapper.Map<Foo,Foo2>(src);
if (mapped.Bar == null) mapped.Bar = new BarViewModel();

但这有点难看。

想法?

4

5 回答 5

36

您可以使用自定义值解析器。以下应该有效:

Mapper.CreateMap<Foo, Foo2>()
   .ForMember(dest => dest.Bar, opt => opt.ResolveUsing(src => src.Bar == null ? new Bar() : Mapper.Map<Bar,Bar2>(src.Bar)))
于 2012-07-19T07:31:14.500 回答
9

现在您可以使用.NullSubstitute()在 Automapper 中将 NULL 值替换为一些自定义值,例如:

CreateMap<SMModel, VM_SMModel>()
                    .ForMember(d => d.myDate, o => o.NullSubstitute(new DateTime(2017,12,12)));
于 2016-09-20T19:42:06.097 回答
8

从 Automapper 8 开始,ResolveUsing 不再是一个选项,而是 inlineFunc的,IValueResolver并且IMemberValueResolver是 .

内联函数示例

Mapper.Initialize(cfg =>
{
  cfg.CreateMap<Foo, FooViewModel>()
     .ForMember(dest => dest.BarViewModel,
       opt  => opt.MapFrom((src, dest) =>
       {
         if (src.Bar == null)
           return new BarViewModel ();

           return Mapper.Map<Bar, BarViewModel>(src.Bar);
        }));

  cfg.CreateMap<Bar, BarViewModel>();
});

IMemberValueResolver 示例

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<Foo, FooViewModel>()
       .ForMember(dest => dest.BarViewModel,
                  opt  => opt.MapFrom<NullBarResolver, Bar>(src => src.Bar));

    cfg.CreateMap<Bar, BarViewModel>();
});

public class NullBarResolver : IMemberValueResolver<object, object, Bar, BarViewModel>
{
    public BarViewModel Resolve(object source, object destination, Bar sourceMember,
                                BarViewModel destMember, ResolutionContext context)
    {
        if (sourceMember == null)
            return new BarViewModel();

        return Mapper.Map(sourceMember, destMember);
    }
}

这里有一些关于自定义值解析器的好文档。

工作演示

于 2018-12-13T19:06:12.523 回答
3

我没有收到以下编译器错误:

public class Foo
{
    public Bar Bar { get; set; }
}

public class Foo2
{
    public Bar Bar { get; set; }
}

public class Bar
{
    public int Id { get; set; }

    public Bar()
    {
        Id = 3;
    }
}

CreateMap<Foo, Foo2>()
    .ForMember(
        dest => dest.Bar,
        opt => opt.MapFrom(src => src.Bar == null ? new Bar() : src.Bar));

...所以我想知道问题是否实际上与您的映射无关?

于 2012-07-19T08:31:29.637 回答
0

这可以通过PreCondition()方法来完成。这是我编写的一个扩展方法,可以更轻松地做到这一点:

    public static IMappingExpression<TSource, TDestination> MapIf<TSource, TDestination>(
        this IMappingExpression<TSource, TDestination> map, Expression<Func<TDestination, object>> selector,
        Func<TSource, bool> mapIfCondition, Expression<Func<TSource, object>> mapping)
    {
        map.ForMember(selector, c =>
        {
            c.MapFrom(mapping);
            c.PreCondition(mapIfCondition);
        });
        return map;
    }

使用示例:

//if settings are null coming from the sender, then ignore them and keep the current settings
CreateMap<PresentationView, Presentation>()
   .MapIf(x => x.Settings, x => x.Settings is not null, v => v.Settings!)

于 2022-01-24T14:24:53.107 回答