web-dev-qa-db-ja.com

AutoMapperマップがnullでない場合、それ以外の場合はカスタム変換

これが私のコードです:

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();

しかし、それは少し醜いです。

アイデア?

31
RPM1984

カスタム値リゾルバー を使用できます。以下はうまくいくはずです:

Mapper.CreateMap<Foo, Foo2>()
   .ForMember(dest => dest.Bar, opt => opt.ResolveUsing(src => src.Bar == null ? new Bar() : Mapper.Map<Bar,Bar2>(src.Bar)))
36
k0stya

これで、.NullSubstitute()を使用して、AutomapperでNULL値をカスタム値に置き換えることができます。例:

CreateMap<SMModel, VM_SMModel>()
                    .ForMember(d => d.myDate, o => o.NullSubstitute(new DateTime(2017,12,12)));
9
Vijai

Automapper 8以降、ResolveUsingオプションではなくなりました ですが、インラインFunc 's、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);
    }
}

ここにカスタム値リゾルバー に関する優れたドキュメントがあります。

作業デモ

3
spottedmahn

次の場合、コンパイラエラーは発生しません。

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));

...それで、問題が実際にマッピングにあるのではないかと思いますか?

3
devuxer