Ignora il mapping di una proprietà con Automapper


285

Sto usando Automapper e ho il seguente scenario: Class OrderModel ha una proprietà chiamata 'ProductName' che non è nel database. Quindi quando provo a fare il mapping con:

Mapper.CreateMap<OrderModel, Orders>(); 

Genera un'eccezione:

"Le seguenti 1 proprietà su Project.ViewModels.OrderModel non sono mappate: 'ProductName'

Nel Wiki di AutoMapper per Proiezioni ho letto il caso opposto (l'attributo extra è sulla destinazione, non nella fonte che è in realtà il mio caso)

Come posso evitare automapper per eseguire il mapping di questa proprietà?


7
Automapper non funziona in questo modo. Si preoccupa solo delle proprietà sull'oggetto di destinazione. Src può contenere 100 proprietà aggiuntive: Automapper mappa solo le proprietà dest. Ci deve essere qualcos'altro che causa l'eccezione di mappatura. Puoi pubblicare un codice di ciò che non funziona?
Patrick Steele,

Fa quello che chiedi automaticamente. Pubblica del codice per chiarire
BeRecursive,

Dai un'occhiata ai seguenti post, questi potrebbero aiutarti a stackoverflow.com/questions/4456519/… stackoverflow.com/questions/4052579/…
Divi

3
@Patrick AutoMapper fa alcuni trucchi con l'analisi dei nomi di metodi / proprietà. È possibile che sia presente una proprietà sull'origine che viene mappata involontariamente anche se non esiste una corrispondenza esatta sulla destinazione. Questo è il motivo per cui esiste un ForSourceMember (... Ignore ()) per impedirlo quando si verifica.
AaronLS,

Risposte:


478

Da Jimmy Bogard: CreateMap<Foo, Bar>().ForMember(x => x.Blarg, opt => opt.Ignore());

È in uno dei commenti sul suo blog .


13
Inoltre, CreateMap<Foo, Bar>().ForSourceMember(x => x.Blarg, opt => opt.Ignore());potrebbe essere utile
stackoverfloweth

5
@stackoverfloweth ricerca Non vuoi dire: CreateMap<SourceType, DestType> (MemberList.Source).ForSourceMember(x => x.MySourceProperty, opt => opt.DoNotValidate())?
monty,

13
Ignore è stato sostituito con DoNotValidate in ForSourceMember: github.com/AutoMapper/AutoMapper/blob/master/docs/…
Jamie,

@Jamie @monty - Ho iniziato ad aggiornare questo re: il tuo commento, ma sembra che la modifica della sintassi influisca solo sul caso di proiezione (in cui la proprietà di origine deve essere ignorata). La richiesta del PO è di ignorare una proprietà di destinazione, quindi Ignore()rimane la sintassi corretta. Questo perché la modifica della sintassi per è Ignorestata apportata ISourceMemberConfigurationExpressionsull'interfaccia ma non sull'interfaccia disgiunta IMemberConfigurationExpression`3.
smartcaveman,

2
@Franva ForMember () è in realtà "ForDestinationMember ()"
rvnlord

243

Sono forse un po 'perfezionista; Non mi piace molto la sintassi ForMember (..., x => x.Ignore ()). È una piccola cosa, ma per me è importante. Ho scritto questo metodo di estensione per renderlo un po 'più bello:

public static IMappingExpression<TSource, TDestination> Ignore<TSource, TDestination>(
    this IMappingExpression<TSource, TDestination> map,
    Expression<Func<TDestination, object>> selector)
{
    map.ForMember(selector, config => config.Ignore());
    return map;
}

Può essere usato così:

Mapper.CreateMap<JsonRecord, DatabaseRecord>()
        .Ignore(record => record.Field)
        .Ignore(record => record.AnotherField)
        .Ignore(record => record.Etc);

Potresti anche riscriverlo con cui lavorare params, ma non mi piace l'aspetto di un metodo con un sacco di lambda.


6
So che questo va oltre la domanda iniziale, ma mi piace molto questa risposta, è pulita, molto facile da leggere e da capire all'istante e facile da riutilizzare
Lski,

Per quanto riguarda params: Potresti restituire una serie di selettori dall'interno di una singola lambda, quindi mappare ogni selettore con foreacho Select()forse non meno disordinato, però.
jpaugh

grazie @Steve Rukuts, per chiunque sia alla ricerca di un metodo di estensione per ignorare i membri di origine, è possibile utilizzare questo IMappingExpression statico pubblico <TSource, TDestination> IgnoreSourceValidation <TSource, TDestination> (this IMappingExpression <TSource, TDestination> map, Expression <Func <TSource , oggetto >> selettore) {map.ForSourceMember (selettore, config => config.DoNotValidate ()); mappa di ritorno; }
Jason Dias il

79

Puoi farlo:

conf.CreateMap<SourceType, DestinationType>()
   .ForSourceMember(x => x.SourceProperty, y => y.Ignore());

Automapper ha un'estensione ForSourceMember?
Redatto il 1

Lo faccio attualmente, ma sarebbe l'ideale NON dover creare tutti questi Ignora ...: /
Tom Stickel

sai se c'è un modo per ignorare quando si esegue effettivamente la mappatura e non quando si crea la mappa?
Sam, sono io, dice Reinstate Monica, il


3
Per lo scenario indicato nella domanda, questa dovrebbe essere la risposta accettata. La risposta attualmente accettata ignora il mapping delle proprietà nell'oggetto di destinazione. Questa domanda sta ponendo domande sull'ignorare i mapping nell'oggetto sorgente.
Rob S.

28

Solo per chiunque cerchi di farlo automaticamente, puoi utilizzare quel metodo di estensione per ignorare le proprietà inesistenti sul tipo di destinazione:

public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    var sourceType = typeof(TSource);
    var destinationType = typeof(TDestination);
    var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType)
        && x.DestinationType.Equals(destinationType));
    foreach (var property in existingMaps.GetUnmappedPropertyNames())
    {
        expression.ForMember(property, opt => opt.Ignore());
    }
    return expression;
}

da utilizzare come segue:

Mapper.CreateMap<SourceType, DestinationType>().IgnoreAllNonExisting();

grazie a Can Gencer per l'informazione :)

fonte: http://cangencer.wordpress.com/2011/06/08/auto-ignore-non-existing-properties-with-automapper/



1
Questo non funziona quando si inietta IMapper. Mapper.GetAllTypeMaps non esiste nell'ultima versione di AutoMapper. Inoltre, quando installo le mie mappe in AutoMapper.Profile e successivamente ho iniettato IMapper, ho ricevuto questa eccezione "Mapper non inizializzato. Chiama Inizializza con la configurazione appropriata. Se stai cercando di utilizzare le istanze del mapper attraverso un contenitore o in altro modo, assicurati di non hai chiamate ai metodi statici Mapper.Map e, se stai utilizzando i metodi di estensione ProjectTo o UseAsDataSource, assicurati di passare l'istanza IConfigurationProvider appropriata. "
Ristogod,

Ho appena 'Mapper' does not contain a definition for 'GetAllTypeMaps' [DSSTools]..
Bassie,

2
@Bassie Usa la Mapper.Configuration.GetAllTypeMaps() fonte
Mike Bovenlander,

28

Ora c'è (AutoMapper 2.0) un IgnoreMapattributo, che userò piuttosto che la sintassi fluida che è un po 'pesante IMHO.


35
Tuttavia, l'attributo ignore perde il mapping automatico nell'applicazione.
Phill,

11
AutoMapper è una cosa che non mi dispiace perdere dappertutto. ;)
Pawel Krakowiak,

4
Puoi sempre considerare di derivare IgnoreMapAttribute.
Alapago,

1
Questo è un buon modo per ignorare una proprietà di base ereditata da molti oggetti. Salva da dover ignorarlo in ogni configurazione di mappatura.
Chase Florell,

23

Quando si associa un modello di visualizzazione a un modello di dominio, può essere molto più semplice convalidare semplicemente l'elenco dei membri di origine anziché l'elenco dei membri di destinazione

Mapper.CreateMap<OrderModel, Orders>(MemberList.Source); 

Ora la mia convalida della mappatura non fallisce, richiedendone un'altra Ignore()ogni volta che aggiungo una proprietà alla mia classe di dominio.


7
QUESTO è quello che cercavo, così utile quando si modificava solo un sottoinsieme delle proprietà degli oggetti di dominio da un DTO molto più semplice.
Adam Tolley,

5
Questa è la risposta, ragazzi, rendetelo ufficiale in modo che i neofiti non vengano confusi
Piotr M

0

Potrebbe usare IgnoreAttribute sulla proprietà che deve essere ignorata


2
È [IgnoreMap]diIgnoreMapAttribute
fiorebat il

-5

Ciao a tutti Si prega di utilizzare questo sta lavorando bene ... per l'uso di auto mapper multipla .ForMember in C #

        if (promotionCode.Any())
        {
            Mapper.Reset();
            Mapper.CreateMap<PromotionCode, PromotionCodeEntity>().ForMember(d => d.serverTime, o => o.MapFrom(s => s.promotionCodeId == null ? "date" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", DateTime.UtcNow.AddHours(7.0))))
                .ForMember(d => d.day, p => p.MapFrom(s => s.code != "" ? LeftTime(Convert.ToInt32(s.quantity), Convert.ToString(s.expiryDate), Convert.ToString(DateTime.UtcNow.AddHours(7.0))) : "Day"))
                .ForMember(d => d.subCategoryname, o => o.MapFrom(s => s.subCategoryId == 0 ? "" : Convert.ToString(subCategory.Where(z => z.subCategoryId.Equals(s.subCategoryId)).FirstOrDefault().subCategoryName)))
                .ForMember(d => d.optionalCategoryName, o => o.MapFrom(s => s.optCategoryId == 0 ? "" : Convert.ToString(optionalCategory.Where(z => z.optCategoryId.Equals(s.optCategoryId)).FirstOrDefault().optCategoryName)))
                .ForMember(d => d.logoImg, o => o.MapFrom(s => s.vendorId == 0 ? "" : Convert.ToString(vendorImg.Where(z => z.vendorId.Equals(s.vendorId)).FirstOrDefault().logoImg)))
                .ForMember(d => d.expiryDate, o => o.MapFrom(s => s.expiryDate == null ? "" : String.Format("{0:dd/MM/yyyy h:mm:ss tt}", s.expiryDate))); 
            var userPromotionModel = Mapper.Map<List<PromotionCode>, List<PromotionCodeEntity>>(promotionCode);
            return userPromotionModel;
        }
        return null;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.