2010-12-06 18 views
54

Existe-t-il un moyen de le faire? Nous avons un récapitulatif pour les mappages de trois types différents, et lorsque nous créons une carte pour chaque type, les accessoires qui ne sont pas mappés émettent une erreur. Il y a environ 35 attributs sur le résumé dto. Pour utiliser l'option Ignore() sur chacun d'eux, c'est trop de problèmes. Y a-t-il un ignorant global? Quelque chose commeComment ignorer tous les membres de destination, à l'exception de ceux qui sont mappés?

CreateMap<Source,Target>() 
    .IgnoreAllUnmapped(); 
+5

Cela semble être une bonne chose à faire, cependant, même si il y a 35 propriétés sur votre DTO, si vous utilisez 'AutoMapper.Mapper.AssertConfigurationIsValid();' il est possible que vous oubliez pas de carte une propriété dans le futur et cela pourrait conduire à des problèmes. Je voudrais utiliser avec ** prudence **. – CodeMonkeyKing

+6

Depuis la version 5.0+, vous pouvez utiliser: '.ForAllOtherMembers (m => m.Ignore()) '. Voir l'exemple [ici] (http://stackoverflow.com/a/39110565/264672) –

Répondre

90

Cela fonctionne pour moi:

public static class MappingExpressionExtensions 
{ 
    public static IMappingExpression<TSource, TDest> IgnoreAllUnmapped<TSource, TDest>(this IMappingExpression<TSource, TDest> expression) 
    { 
     expression.ForAllMembers(opt => opt.Ignore()); 
     return expression; 
    } 
} 

Because ForAllMembers retours void, appelant ForAllMembers(o => o.Ignore()) sans cette méthode d'extension ne fonctionnerait pas. Nous voulons garder l'expression de cartographie disponible pour permettre aux applications suivantes:

CreateMap<Source, Destination>() 
      .IgnoreAllUnmapped() 
      .ForMember(d => d.Text, o => o.MapFrom(s => s.Name)) 
      .ForMember(d => d.Value, o => o.MapFrom(s => s.Id)); 
+0

Ceci supprime et ignore les mappages conventionnels. Y a-t-il un moyen de conserver les mappings conventionnels? –

+2

@JoaoLeme Je pense que vous devez décider ce que vous essayez d'accomplir. Ignorer tous les membres devrait être rarement utilisé. Je ne suis pas sûr comment AutoMapper pourrait faire la détermination de la façon de garder ce que vous avez appelé "mappages conventionnels" mais exclure le non cartographié. Je pense qu'il est préférable d'indiquer explicitement dans votre mappage quels membres vous devez gérer -ou- utilisez l'extension IgnoreAllUnmapped et spécifiez que vous voulez uniquement que les membres explicitement définis soient mappés. Peut-être un exemple de ce que vous devez accomplir pourrait illustrer pourquoi vous posez cette question particulière. – CodeMonkeyKing

+1

@JoaoLeme vous pouvez également vérifier cette réponse - [AutoMapper IgnoreTheRest] (http://stackoverflow.com/questions/954480/automapper-ignore-the-rest/6474397#6474397) - qui a été souligné par Edward Brey dans son répondre à cette question. – CodeMonkeyKing

1

Essayez d'utiliser .ConvertUsing() dans votre cas, par exemple Ainsi, vous pouvez décrire toutes les propriétés que vous voulez avoir dans votre objet, les autres seront ignorées.

+0

cela ne fonctionne pas, tous les autres champs ne sont pas ignorés ils sont simplement remplis avec les valeurs par défaut – Para

+0

Depuis que j'instancie un nouvel objet (Cible) Je veux que les propriétés ignorées aient leur valeur par défaut, donc c'est bien. – DownChapel

24

J'ai lutté avec celui-ci pendant un bon moment aussi, ou du moins un problème similaire à celui-ci. J'ai eu une classe avec beaucoup de propriétés (environ 30) et je voulais seulement cartographier environ 4 d'entre eux. Il semble fou d'ajouter 26 instructions ignorer (surtout quand cela signifie que les futures modifications de la classe signifiera devoir les mettre à jour!)

J'ai finalement trouvé que je pouvais dire à AutoMapper d'ignorer tout, puis d'ajouter explicitement ceux qui Je voulais.

// Create a map, store a reference to it in a local variable 
var map = CreateMap<Source,Target>(); 

// Ignore all members 
map.ForAllMembers(opt => opt.Ignore()); 

// Add mapping for P1 
map.ForMember(dest => dest.P1, opt => opt.MapFrom(src => src.P1)); 

// Add other mappings... 
map.ForMember(dest => dest.P2, opt => opt.MapFrom(src => src.P2)); 
map.ForMember(dest => dest.P3, opt => opt.MapFrom(src => src.P3)); 
map.ForMember(dest => dest.P4, opt => opt.MapFrom(src => src.P4)); 

Vous seriez pardonné de penser que vous pouvez simplement le faire (mais ne sont pas parce qu'il compilez coutume):

// This won't compile 
CreateMap<Source,Target>() 
    .ForAllMembers(opt => opt.Ignore()) 
    .ForMember(dest => dest.P1, opt => opt.MapFrom(src => src.P1)); 

La raison pour laquelle cela ne fonctionne pas est que les ForAllMembers La méthode() ne supporte pas le style fluide de chaînage (au moins dans la version actuelle 2.0).

La bonne nouvelle est que la version sans chaînage fonctionne bien. Le seul inconvénient est que vous devez indiquer explicitement à AutoMapper quels membres doivent être mappés. Je n'ai pas encore trouvé un moyen facile de l'avoir dans les deux sens, de sorte que vous pouvez toujours utiliser les mappages implicites et ignorer ceux qui sont cassés.

+0

Vous n'avez pas nécessairement besoin de stocker le 'map' dans une variable comme ça. AutoMapper met à jour le mappage existant si vous le créez plusieurs fois (oui, probablement pas très intuitif, mais c'est comme ça que ça fonctionne). Ainsi, dans votre exemple, vous pouvez appeler 'CreateMap ... Ignore()', puis 'CreateMap ... ForMember() ... ForMember() ...' sans aucun problème. Je ne sais pas pourquoi Jimmy a décidé de ne pas renvoyer l'expression de mappage de 'ForAllMembers', car cela aurait permis de chaîner normalement. – julealgon

5

Pour éviter d'avoir à spécifier explicitement les propriétés mappées, vous pouvez utiliser IgnoreAllNonExisting. Il ignore les propriétés de destination qui n'ont pas de propriétés source mappées.

1

méthode d'extension qui permet la syntaxe couramment la méthode ForAllMembers:

public static IMappingExpression<TSource, TDestination> IgnoreAllMembers<TSource, TDestination>(
    this IMappingExpression<TSource, TDestination> expression 
    ) 
{ 
    expression.ForAllMembers(opt => opt.Ignore()); 
    return expression; 
} 

Utilisation:

L'appel à IgnoreAllMembers doit être avant l'appel à ForMember.

 CreateMap<LocationRevision, Dto.LocationAddressMap>() 
      .IgnoreAllMembers() 
      .ForMember(m => m.LocationId, opt => opt.MapFrom(src => src.Id)) 
      ;