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.