2013-03-11 7 views
11

Esiste comunque in Automapper la possibilità di ignorare tutte le proprietà di un determinato tipo? Stiamo provando a migliorare la qualità del nostro codice convalidando i mapping di Automapper ma dovendo mettere uno .Ignore() per tutti gli IEnumerable<SelectListItem> che sono sempre creati manualmente sta creando attriti e rallentando lo sviluppo.Automapper: ignora tutti gli elementi di IEnumerable <SelectListItem>

Qualche idea?

possibile idea dopo aver creato mappature:

var existingMaps = Mapper.GetAllTypeMaps(); 
    foreach (var property in existingMaps) 
    { 
     foreach (var propertyInfo in property.DestinationType.GetProperties()) 
     { 
      if (propertyInfo.PropertyType == typeof(List<SelectListItem>) || propertyInfo.PropertyType == typeof(IEnumerable<SelectListItem>)) 
      { 
       property.FindOrCreatePropertyMapFor(new PropertyAccessor(propertyInfo)).Ignore(); 
      } 
     } 
    } 

risposta

17

Automapper attualmente non supporta proprietà type basato ignora.

Attualmente ci sono tre modi di ignorare le proprietà:

  • utilizzare le opzioni Ignore() quando si crea il mapping

    Mapper.CreateMap<Source, Dest>() 
        .ForMember(d => d.IgnoreMe, opt => opt.Ignore()); 
    

    questo è ciò che si vuole evitare.

  • Annota sulle tue IEnumerable<SelectListItem> proprietà con il il IgnoreMapAttribute

  • Se i nomi di proprietà IEnumerable<SelectListItem> seguono alcune convenzioni di denominazione. Per esempio. tutti quelli iniziano con la parola "Select" è possibile utilizzare il metodo AddGlobalIgnore di ignorarli a livello globale:

    Mapper.Initialize(c => c.AddGlobalIgnore("Select")); 
    

    ma con questo si può abbinare solo con inizia con.

Tuttavia è possibile creare un metodo di estensione comodità per le opzioni di prima che ignorerà automaticamente le proprietà di un determinato tipo quando si chiama CreateMap:

public static class MappingExpressionExtensions 
{ 
    public static IMappingExpression<TSource, TDest> 
     IgnorePropertiesOfType<TSource, TDest>(
     this IMappingExpression<TSource, TDest> mappingExpression, 
     Type typeToIgnore 
     ) 
    { 
     var destInfo = new TypeInfo(typeof(TDest)); 
     foreach (var destProperty in destInfo.GetPublicWriteAccessors() 
      .OfType<PropertyInfo>() 
      .Where(p => p.PropertyType == typeToIgnore)) 
     { 
      mappingExpression = mappingExpression 
       .ForMember(destProperty.Name, opt => opt.Ignore()); 
     } 

     return mappingExpression; 
    } 
} 

E lo si può utilizzare con la seguente modo :

Mapper.CreateMap<Source, Dest>() 
    .IgnorePropertiesOfType(typeof(IEnumerable<SelectListItem>)); 

Quindi ancora non sarà una soluzione globale, ma non c'è bisogno di elencare quali proprietà devono essere ignorati e funziona per più corretta legami dello stesso tipo.

Se non si ha paura di sporcarsi le mani:

Attualmente v'è una soluzione molto hacky che va molto in profondità i meccanismi interni di Automapper.Non so come pubblico è questa API in modo da questo freno soluzione potrebbe in funzione:

È possibile iscriversi sul s' il ConfigurationStoreTypeMapCreated evento

((ConfigurationStore)Mapper.Configuration).TypeMapCreated += OnTypeMapCreated; 

e aggiungere il tipo di base ignorare direttamente sul creato TypeMap casi:

private void OnTypeMapCreated(object sender, TypeMapCreatedEventArgs e) 
{ 
    foreach (var propertyInfo in e.TypeMap.DestinationType.GetProperties()) 
    { 
     if (propertyInfo.PropertyType == typeof (IEnumerable<SelectListItem>)) 
     { 
      e.TypeMap.FindOrCreatePropertyMapFor(
       new PropertyAccessor(propertyInfo)).Ignore(); 
     } 
    } 
} 
+0

Grazie Sì, avevo trovato AddGlobalIgnore ma volevo farlo sul tipo. IgnorePropertiesOfType sembra buono grazie. Semplicemente noioso dobbiamo aggiungerlo a centinaia di VM. Quindi non c'è modo di cercare tutti i modelli mappati e tramite reflection trovare le proprietà con il tipo di IEnumerable e quindi applicare l'attributo ignore? – GraemeMiller

+0

Per aggiungere gli attributi dinamicamente, qualcosa che inietta IL come Postharp. Comunque ho trovato una soluzione golbal piuttosto sporca/hacky. Aggiornerò la mia risposta – nemesv

+0

Sì, stavo solo guardando la fonte. Ho visto dove è stato coinvolto GlobalIgnore pensando di cambiare la fonte per noi, ma sembra che farà il trucco! Grazie – GraemeMiller

0

Se vi imbattete in questo momento, sembra che ci sia un altro modo.

Mapper.Initialize(cfg => 
{ 
    cfg.ShouldMapProperty = pi => pi.PropertyType != typeof(ICommand); 
}); 

Non ho esaminato quando questo è stato introdotto. Questo sembra che bloccherà o permetterà comunque di filtrarlo. Vedi questo: AutoMapper Configuration