2009-11-03 7 views
12

State avendo alcuni problemi reali con automapper. Penso di aver trovato la soluzione ma non sono sicuro di come implementarlo.Utilizzo della versione di istanza di CreateMap e Map con un servizio WCF?

fondamentalmente sto usando una mappatura personalizzata con ResolveUsing e ConstructedBy per passare in params al costruttore, capisco che la maggior parte delle persone lo imposta su global.asax una volta e se ne dimentica.

Ma il problema è che il mio metodo (su un WCF) passa in diverse params al costruttore di un ResolveUsing ......

Prima usavo il Mapper.CreateMap e Mapper.Map che sono metodi statici e sembra che quando diverse petizioni entrano nel servizio wcf tramite metodi (multiutente) sono in conflitto tra loro.

Dopo aver letto qualcosa, è possibile utilizzare la versione di istanza di CreateMap e Map in modo che ogni singola petizione ottenga la propria mappa e possa passare i propri parametri.

Ma non riesco a trovare come farlo. Qualcuno può spiegare per favore? Sono davvero bloccato ...

Prima di tanto in tanto ricevevo errori di chiave duplicati e inoltre inserivo una traccia di log sul costruttore e sembra che 1 petizione stia sovrascrivendo l'altra - da qui le versioni statiche di Mapper.

Beh spero ho ragione, ma non riesco a trovare niente altro ...

a cura - un esempio di quello HO

Fondamentalmente tutto mappatura sta funzionando come dovrebbe, come Sto usando MapFrom nella maggior parte dei casi.

Quindi creo un'istanza del mio Resolver che passo in un URL. Ho controllato l'url prima che lo trasmetta e sia corretto. Ma una volta restituito restituisce l'URL sbagliato.

Il motivo per cui ho bisogno di passare nell'URL è che ha delle variabili lì, quindi ho bisogno di sostituire le variabili ... Fondamentalmente ci sono 2 URL a seconda dell'ufficio e ho i log ovunque e posso vedere cosa sono passando dentro ma una volta che l'ho passato - non è quello che ho passato, se questo ha senso, questo è strano !!

Un servizio WCF e un client hanno chiamato il metodo passando due volte in due uffici diversi, quindi 2 URL diversi. Ma restituiscono sempre lo stesso URL. È come se una sessione stesse sovrascrivendo l'altra ...

Spero che abbia senso.

SalesPointResolver newSalesPointResolver = new SalesPointResolver(returnReservationUrl, reservationSite.ReservationUrl, startDate, endDate, officeCode); 


     Mapper.CreateMap<Models.Custom.House, DTO.House>() 
      .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id)) 
      .ForMember(dest => dest.TaxIncluded, 
         opt => opt.MapFrom(src => src.Segments.FirstOrDefault().TaxIncluded)) 
      .ForMember(dest => dest.TaxPercentage, 
         opt => opt.MapFrom(src => src.Segments.FirstOrDefault().TaxPercentage)) 

      .ForMember(dest => dest.SalesPoints, 
         opt => 
         opt.ResolveUsing(newSalesPointResolver)) 
      ; 

scoperto dove sta venendo a mancare - ma sconosciuto PERCHE

Vedere i miei commenti in linea con il codice. Nel costruttore arriva l'urlTemplate, l'ho salvato in una var privata e poi nel sovrascritto ResolveCore è un'altra cosa :-)

Ho inserito alcuni log4net lì, quindi posso vedere che cosa sta succedendo.

[Log] 
public class SalesPointResolver : ValueResolver<Models.Custom.House, IList<DTO.SalesPoint>> 
{ 
    private readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

    private string urlTemplate; 

    public SalesPointResolver (bool returnReservationUrl, string urlTemplate, DateTime startDate, DateTime endDate, string officeCode) 
    { 
     this.urlTemplate = urlTemplate; 

     log.Error("passed in " + urlTemplate); // THIS IS PERFECT 
     log.Error("I am now " + this.urlTemplate); // THIS IS PERFECT 
    } 

    protected override IList<DTO.SalesPoint> ResolveCore(House source) 
    { 
     this.house = source; 

     log.Error("in resolveCore :" + this.urlTemplate); // THIS IS RETURNING THE WRONG VALUE 

soluzione temporanea

ho fatto una soluzione temporanea, ma è davvero male. Sono sicuro che l'automapper può fare ciò che sto provando, ma ovviamente sto facendo qualcosa di sbagliato.

In sostanza, restituisco tramite LINQ una raccolta di record (QUESTA È LA MIA FONTE), quindi ho inserito un nuovo campo in ogni record che contiene il modello di URL corretto. E poi, invece di passare (tramite costruttore) il template dell'URL, l'ho messo a disposizione come proprietà su OGNI record sulla collezione (THE SOURCE) ... e funziona perfettamente.

Ovviamente, questa è davvero una patch e non ideale ma mi fa girare.

Dove sto andando male?

+0

Nel tuo esempio è vero che non si conosce l'origine fino al runtime ma sai a quale target stai mappando al momento della compilazione? –

+0

No so la fonte ... ma sto passando in variabili a ResolveUsing utilizzando il costruttore quindi la mappa deve essere creata ogni volta e non deve essere condivisa da altre sessioni ecc. –

+0

Se questo è un servizio WCF è in esecuzione nel suo il proprio dominio app in modo che le mappe non vengano condivise con altri processi. Sembra che gli argomenti di ResolveUsing varino, ma ResolveUsing prende tipicamente il tipo di sorgente. Qual è il motivo per cui devi passare argomenti nel costruttore del tuo Value Resolver personalizzato che è al di fuori del tuo tipo di sorgente? –

risposta

2

Beh, sembra che la mia domanda è abbandonata, ma dopo un po 'di tempo a giocare intorno alla fine ho trovato un buon correzione ..

fondamentalmente ero dentro una volontà e ho avuto un'altra mappa che una delle proprietà chiamato un'altra ResolveUsing ...

Sembra che ci sia un problema con questo. Un'altra cosa strana è che ha fallito ogni volta che il pool di applicazioni è stato avviato o riciclato. Quindi è fallito la prima volta e poi è andato bene fino a quando il riciclo è avvenuto (sto usando un'app wcf).

Così ho sostituito la seconda Mapping con un foreach e ha fatto il mio mappatura del genere dentro il mio Resolve originale ...

ho messo qui la risposta nel caso in cui esso può aiutare chiunque altro in futuro ..

stavo usando i metodi statici Mapper per fare le mie mappature, questi non erano in global.asax come ho bisogno di passare cose diverse a seconda di alcuni fattori ..

mi sono sempre chiesto se fosse possibile farlo con le versioni di istanza di mappper, anche se esisteva ..... ma non l'ho mai scoperto ..

Ma comunque tutto funziona al 100% la società ...

+0

Potresti rispondere http://stackoverflow.com/questions/9498962/contract-first-soa-designing-business-domain-wcf? – Lijo

1

Hai guardato utilizzando la chiamata Mappa che include l'oggetto di destinazione?

var bar = new Bar ("Personalizzato ogni chiamata");

Mapper.Map (foo, bar);

+0

Grazie jimmy, non sono sicuro Ho capito perfettamente. Se cambio la mappa, non avrò accesso al mio oggetto src standard di cui ho bisogno poiché normalmente mappo solo su alcune proprietà che richiedono di chiamare lo speciale ResolveUsing e il passaggio di un parametro dato che c'è un bel po 'di tempo di logica qui ... Quindi nel risolvere il problema sto ancora usando il mio oggetto src standard ma applicando una logica extra prima di tornare (in questo caso un stringg) - sto fraintendendoti? –

+0

se potessi elaborare lo apprezzerei molto. –

+0

Penso di aver frainteso: hai qualche piccolo frammento che mostra come stai usando le chiamate CreateMap e Map? –

1

Se si desidera utilizzare una versione istanziata del Mapper in Automapper, allora penso che si può utilizzare la classe MappingEngine. Credo che la classe statica Mapper istanzia e configura un oggetto MappingEngine per eseguire tutto il lavoro di mappatura nitty gritty.

Ecco un esempio di applicazione di CIO di Automapper (che richiede di un'istanza del MappingEngine)

http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/05/11/automapper-and-ioc.aspx

34

Sì, c'è un modo per utilizzare una versione istanza di automapper.

Invece di ...

Mapper.CreateMap<Dto.Ticket, Entities.Ticket>() 

è possibile utilizzare:

var configurationStore = 
    new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers); 
var mapper = new MappingEngine(configurationStore); 
configurationStore.CreateMap<Dto.Ticket, Entities.Ticket>() 
+20

Non conosco le versioni precedenti di AutoMapper, ma nella versione corrente, la classe 'Configuration' è denominata' ConfigurationStore'. –

+2

E il metodo 'AllMappers()' è ora una proprietà chiamata 'Mappers'. – bugged87

13

In risposta alla Luke Woodwards s' comment sulla nuova sintassi:

ConfigurationStore store 
    = new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers); 
store.AssertConfigurationIsValid(); 
MappingEngine engine = new MappingEngine(store); 

//add mappings via Profiles or CreateMap 
store.AddProfile<MyAutoMapperProfile>(); 
store.CreateMap<Dto.Ticket, Entities.Ticket>(); 
Problemi correlati