web-dev-qa-db-fra.com

AutoMapper Map si non nul, sinon conversion personnalisée

Voici mon code:

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

Fondamentalement, "BarViewModel" a un ctor sans paramètre qui définit les propriétés de la classe. 

J'essaie donc de dire à AutoMapper:

Si la valeur est null, utilisez le ctor pour la classe. sinon, utilisez la cartographie que vous avez en place

Ce qui précède me donne une erreur de compilation C #. Et je suppose qu'un casting ne fonctionnerait pas non plus.

Y a-t-il un truc d'AutoMapper pour le faire?

Dans le pire des cas, je pourrais supprimer ce mappage pour cette propriété et faire:

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

Mais c'est un peu moche.

Des idées?

26
RPM1984

Vous pouvez utiliser valeur personnalisée résolveur . Ce qui suit devrait fonctionner:

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

Vous pouvez maintenant utiliser .NullSubstitute() pour remplacer la valeur NULL par une valeur personnalisée dans Automapper, par exemple:

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

Je ne reçois pas d'erreur de compilation pour les éléments suivants:

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

... alors je me demande si le problème ne vient pas de votre cartographie?

2
devuxer

A partir de Automapper 8, ResolveUsingn'est plus une option mais inline Func 's, IValueResolver et IMemberValueResolver sont ????.

Exemple de fonction en ligne

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 Exemple

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

Il y a de la bonne documentation sur Custom Value Resolvers here .

_ { Démo de travail } _

1
spottedmahn