web-dev-qa-db-fra.com

Comment ignorer les valeurs NULL pour tous les membres source lors du mappage dans Automapper 6?

J'ai cherché partout: stackoverflow, documentation sur les applications automatiques, internets et je n'ai trouvé aucune information à ce sujet, même si cela semble être un problème très courant.

Ma cartographie:

CreateMap<StatusLevelDTO, StatusLevel>()
            .ForAllMembers(opt => opt.Condition(src => src != null));

Cela ne fonctionne pas car src représente un objet source (StatusLevelDTO), pas une propriété source (je pense).

Pour être plus précis, si je mappe ObjectA à ObjectB, ObjectA.SomeValue est null et ObjectB.SomeValue est 2, je veux que l'objet de destination garde sa valeur (2).

J'ai vu cette question: Automapper ignore les valeurs null avec un résolveur personnalisé et a essayé les deux premières réponses, mais elles semblent toutes deux obsolètes pour la version 6.

Existe-t-il un moyen de faire cela dans Automapper 6? J'utilise 6.0.2 pour être exact.

21
Sikor

Méthode Condition a maintenant cinq surcharges, dont l'une accepte le prédicat de type 

Func<TSource, TDestination, TMember, bool>

ce paramètre TMember est le membre source. Donc, vous pouvez vérifier le membre source pour null:

CreateMap<StatusLevelDTO, StatusLevel>()
     .ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null));
36

La solution ici fonctionne pour mon projet, qui utilise AutoMapper 6.0.2. Dans les projets précédents utilisant AutoMapper 4, j'avais utilisé IsSourceValueNull pour obtenir le même comportement.

J'ai apporté un petit changement à la solution d'origine. Au lieu de vérifier le type de la propriété à mapper, j'ai défini le filtre dans ForAllPropertyMaps pour vérifier le type de l'objet source, afin que le résolveur personnalisé ne s'applique qu'aux mappes de cet objet source. Mais le filtre peut être réglé sur n'importe quoi si nécessaire.

var config = new MapperConfiguration(cfg =>
{
    cfg.ForAllPropertyMaps(
        pm => pm.TypeMap.SourceType == typeof(<class of source object>),
        (pm, c) => c.ResolveUsing<object, object, object, object>(new IgnoreNullResolver(), pm.SourceMember.Name));
});

class IgnoreNullResolver : IMemberValueResolver<object, object, object, object>
{
    public object Resolve(object source, object destination, object sourceMember, object destinationMember, ResolutionContext context)
    {
        return sourceMember ?? destinationMember;
    }
}
5
Tim

Je me suis inspiré de la réponse de @Sergey Berezovskiy pour créer cette configuration pour tous les membres de toutes les cartes de la configuration principale:

Mapper.Initialize(cfg =>
{
  cfg.ForAllMaps((obj, cnfg) => cnfg.ForAllMembers(opts => opts.Condition((src, dest, srcMember) => srcMember != null)));
}
0
Farid Imranov