2012-11-21 16 views
31

Ho aggiornato da AutoMapper 2.0.0 a 2.2.0 oggi e ho realizzato che l'aggiornamento ha rotto del codice. Volevo chiederlo qui prima di pubblicare un problema sul sito github di automapper.Si tratta di una modifica tra AutoMapper 2.0.0 e 2.2.0?

Uno dei miei tipi di destinazione inizializza una proprietà della raccolta in questo modo:

public class PageOf<TModel> 
{ 
    public PageOf() 
    { 
     Items = Enumerable.Empty<TModel>(); 
    } 

    public IEnumerable<TModel> Items { get; set; } 
} 

Con automapper 2.0.0, questo andava bene. Quando ho aggiornato alla versione 2.2.0, l'associazione a questo tipo di destinazione ha causato una NotSupportedException con il messaggio "La raccolta era di una dimensione fissa". (Tale eccezione è stata avvolta all'interno di un'AutoMapperMappingException.)

sono stato in grado di risolvere il problema modificando il codice del costruttore sopra a questo:

public PageOf() 
{ 
    Items = new List<TModel>(); 
} 

Sembra come se automapper 2.0.0 è stato scartando qualsiasi valore era nella proprietà Items e utilizzando l'accessorio di proprietà set, mentre AutoMapper 2.2.0 utilizza semplicemente l'accessor di proprietà get e tenta di modificare l'oggetto IEnumerable esistente. Sembra che Enumerable.Empty<TModel>() stia semplicemente sostituendo una matrice di lunghezza zero, il che spiegherebbe l'eccezione.

È un bug? Cosa in AutoMapper è cambiato tra 2.0.0 e 2.2.0 che gli avrebbe fatto ignorare il setter della proprietà di destinazione e provare invece a modificare la collezione esistente?

Aggiornamento:

Come richiesto, ecco la chiamata CreateMap:

public class PagedQueryResultToPageOfItemsProfiler : Profile 
{ 
    protected override void Configure() 
    { 
     CreateMap<PagedQueryResult<EstablishmentView>, PageOfEstablishmentApiModel>(); 
    } 
} 

La classe PageOfEstablishmentApiModel eredita da PageOf<EstablishmentApiModel>.

ecco il codice Mapper.Map:

var query = Mapper.Map<EstablishmentViewsByKeyword>(input); 
var results = _queryProcessor.Execute(query); 
var model = Mapper.Map<PageOfEstablishmentApiModel>(results); // exception here 

Se una configurazione speciale mappatura è necessaria (for example .ConvertUsing(x => x)) in automapper passando da 2.0.0 a 2.2.0, possiamo avere di aggrapparsi alla vecchia versione. Mi è sempre piaciuto come AM abbia convertito automaticamente le proprietà delle raccolte e, senza di esse, AM sembra più simile a ValueInjecter.

+0

Puoi pubblicare anche il tuo codice Automapper? es .: chiamate di metodo 'Mapper.Map' (stai usando metodi generici?). Questo è probabilmente "di progettazione" e facilmente ripristinato al tuo vecchio comportamento con il giusto metodo di mappatura o configurazione del mappatore. Puoi restituire un array da automapper e assegnarlo alla tua proprietà IEnumerable come nei documenti su github. Pubblicherò un esempio o due come risposta una volta che vedrò il tuo codice che esegue la mappa. – BenSwayne

+2

Non sembra che qui avrai molta fortuna. Ti suggerisco di chiedere sulla [mailing list di AutoMapper] (https://groups.google.com/forum/?fromgroups#!forum/automapper-users) - ecco dove si trovano gli esperti :) – Mightymuke

+0

Hai già recensito AutoMapper 2.2 .0 supporto per mantenere la compatibilità all'indietro? Vi sono casi in cui funzionalità/funzionalità vengono sospese (non più supportate) da un prodotto e le nuove versioni richiedono il refactoring delle app. – G21

risposta

1

Hai provato a utilizzare il metodo mappa in questo modo: Mapper.Map<DestinationClass, SourceClass>(object to convert)

?

Con la versione 2.2 di AutoMapper, questo è il modo in cui lo usiamo e funziona perfettamente per noi.

+2

Sì, se leggi il codice nella domanda, questo è quello che sto facendo. – danludwig

+0

Spiacente, ho modificato la mia risposta perché i tipi generici non sono stati visualizzati. Volevo chiedere se stavi specificando la classe di origine e la classe di destinazione quando chiami il metodo Map. –

0

Suppongo che stia tentando di aggiungere alla raccolta, ma poiché la raccolta è un'istanza di sola lettura (Enumerable.Empty<T>), non può effettivamente modificarla. Immagino che tu abbia ragione sul fatto che AutoMapper abbia cambiato il codice su come istanziano il nuovo tipo. Utilizzare invece un'istanza mutabile come new List<T>() o T[].

+0

Non penso che 'T []' sia mutabile. Questo è ciò che 'Enumerable.Empty ' usa di default. – danludwig

+0

Ma può essere ridimensionato/mutato, a differenza del riferimento Enumerable.Empty <T> che è di sola lettura. – Haney

+0

L'ultima volta che ho controllato, gli array non possono essere ridimensionati dopo che sono stati creati. Sono di lunghezza fissa. È possibile convertire un array in un elenco, modificarne le dimensioni e quindi riconvertirlo in un altro array, ma non è possibile ridimensionare direttamente un array. – danludwig

Problemi correlati