2009-11-03 5 views
12

Haben Sie einige echte Probleme mit AutoMapper. Ich denke, ich habe die Lösung gefunden, bin mir aber nicht sicher, wie ich sie umsetzen soll.Verwenden der Instanzversion von CreateMap und Map mit einem WCF-Dienst?

Im Grunde benutze ich eine benutzerdefinierte Zuordnung mit ResolveUsing und ConstructedBy, um Parameter an den Konstruktor zu übergeben, ich verstehe, dass die meisten Menschen dies in der global.asax einmal einrichten und vergessen.

Aber das Problem ist, dass meine Methode (auf einem WCF) verläuft in verschiedenen params an den Konstruktor eines ResolveUsing ......

Bevor ich die Mapper.CreateMap und Mapper.Map wurde mit, die statische Methoden und es scheint, dass, wenn verschiedene Petitionen über Methoden (Multiuser) in den WCF-Dienst kommen, sie miteinander in Konflikt stehen.

Nachdem ich etwas gelesen habe, kann ich die Instanz-Version von CreateMap und Map verwenden, so dass jede einzelne Petition ihre eigene Karte bekommt und ihre eigenen Params einreichen kann.

Aber ich kann nicht finden, wie es geht. Kann mir bitte jemand erklären? Ich bin wirklich fest ...

Bevor ich hin und wieder würde ich doppelte Schlüsselfehler bekommen und auch ich eine Protokoll-Trace auf dem Konstruktor und es scheint, dass 1 Petition die andere überschreibt - daher die statischen Versionen von Mapper.

Nun, ich hoffe, ich bin richtig, aber ich kann nichts anderes finden ...

EDITED - ein Beispiel dessen, was ich

Grundsätzlich sind alle Mapping, wie es sollte funktioniert, wie Ich verwende MapFrom in den meisten Fällen.

Dann erstelle ich eine Instanz meines Resolvers, die ich in einer URL übergeben. Ich habe die URL überprüft, bevor ich sie übergebe und sie korrekt ist. Sobald es zurückgegeben wird, wird jedoch die falsche URL zurückgegeben.

Der Grund, warum ich die URL übergeben muss, ist, dass es Variablen drin hat, also muss ich die Variablen ersetzen ... Grundsätzlich gibt es 2 URLs je nach Büro und ich habe Logs überall und ich kann sehen, was ich bin vorbeikommen, aber sobald ich es übergebe - es ist nicht derjenige, an dem ich vorbeikam, wenn das Sinn macht, ist das komisch !!

Es ist ein WCF-Dienst und ein Client hat die Methode zweimal in zwei verschiedenen Büros und damit zwei verschiedenen URLs aufgerufen. Sie geben jedoch immer dieselbe URL zurück. Es ist wie eine Sitzung überschreibt die andere ...

Ich hoffe, das macht Sinn.

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)) 
      ; 

herausgefunden, wo FAILING - aber nicht bekannt, warum

inline meine Kommentare anzeigen mit Code. Im Konstruktor kommt das urlTemplate an, ich speichere es in einer privaten var und dann im überschriebenen ResolveCore, es ist etwas anderes :-)

Ich habe ein paar log4net-Logs dort hingelegt, damit ich sehen kann, was passiert.

[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 

Notlösung

Ich habe eine vorübergehende Lösung getan, aber es ist wirklich schlecht. Ich bin mir sicher, dass Autofahrer das tun können, was ich versuche, aber ich mache offensichtlich etwas falsch.

Grundsätzlich gebe ich über LINQ eine Sammlung von Datensätzen zurück (DAS IST MEINE QUELLE), also habe ich ein neues Feld in jeden Datensatz eingegeben, der die korrekte URL-Vorlage enthält. Und dann, anstatt (über Konstruktor) die URL-Vorlage einzutragen, habe ich sie als Eigenschaft auf JEDEM Datensatz in der Sammlung verfügbar (THE SOURCE) ... und sie funktioniert perfekt.

Natürlich ist das wirklich Patch und nicht ideal, aber es bringt mich zum Laufen.

Wohin gehe ich falsch?

+0

In Ihrem Beispiel ist es, dass Sie nicht wissen, die Quelle bis zur Laufzeit Aber wissen Sie, zu welchem ​​Ziel Sie bei der Kompilierung zugeordnet sind? –

+0

Nein, ich kenne die Quelle ... aber ich übergebe Variablen in ResolveUsing mit Konstruktor daher muss die Karte immer erstellt werden und muss nicht von anderen Sitzungen usw. geteilt werden. –

+0

Wenn dies ein WCF-Dienst ist, wird es in ausgeführt eigene App-Domain, so dass die Karten nicht mit anderen Prozessen geteilt werden. Es klingt wie die Argumente zu ResolveUsing variieren, aber ResolveUsing verwendet den Quellentyp in der Regel. Was ist der Grund dafür, dass Sie Argumente in den Konstruktor Ihres benutzerdefinierten Werte-Resolvers eingeben, die sich außerhalb Ihres Quelltyps befinden? –

Antwort

2

Nun, es scheint, dass meine Frage aufgegeben wird aber nach einer Weile herumspielen fand ich endlich ein gutes fix ..

im Grunde war ich in einem Resolve und ich hatte einen anderen MAP, die eine der Eigenschaften einen anderen ResolveUsing genannt ...

Es scheint, dass es ein Problem damit zu geben scheint. Eine andere seltsame Sache ist, dass es jedes Mal fehlschlug, wenn der Anwendungspool gestartet oder recycelt wurde. Daher ist es beim ersten Mal fehlgeschlagen und dann war es in Ordnung, bis der Recycle passiert ist (ich benutze eine App von wacf).

So ersetzte ich das zweite Mapping mit einer foreach und habe meine Mapping wie das in meinem ursprünglichen Resolve ...

ich die Antwort hier im Falle gestellt haben es jemand anderes in der Zukunft helfen können ..

ich die Mapper statische Methoden wurde mit meinen Zuordnungen zu tun, war diese nicht in global.asax, wie ich verschiedene Dinge in Abhängigkeit von bestimmten Faktoren bestehen muß ..

ich immer gefragt, ob es möglich wäre, es zu tun mit Instanz-Versionen von Mapper, ich obwohl es existiert ..... aber nie herausgefunden ..

Aber trotzdem alles funktioniert 100% jetzt ...

+0

Könnten Sie bitte antworten http://StackOverflow.com/Questions/9498962/contract-first-soa-designing-business-domain-wcf? – Lijo

1

Haben Sie den Map-Aufruf verwendet, der das Zielobjekt aufnimmt?

var bar = neuer Balken ("Custom jeden Anruf");

Mapper.Map (foo, bar);

+0

Danke jimmy, nicht sicher, ich Ich verstehe es ganz. Wenn ich die Karte ändere, dann habe ich keinen Zugriff auf mein Standard-src-Objekt, das ich benötige, da ich es normalerweise nur auf einige Eigenschaften verarbeite, die erfordern, dass ich die spezielle ResolveUsing-Funktion aufrufen und einen Parameter übergeben muss von der Logik hier ... So in der Entschlossenheit benutzend, verwende ich noch mein Standard src Objekt, aber anwendende Logik vor Rückkehr (in diesem Fall ein stringg) - verkenne ich dich? –

+0

Wenn du das ausarbeiten könntest würde ich es sehr schätzen. –

+0

Ich glaube, ich habe es falsch verstanden - haben Sie ein kleines Snippet, das zeigt, wie Sie die CreateMap- und Map-Aufrufe verwenden? –

1

Wenn Sie eine instanzierte Version des Mapper in AutoMapper verwenden möchten, dann denke ich, Sie die MappingEngine Klasse verwenden können. Ich glaube, dass die statische Mapper-Klasse ein MappingEngine-Objekt instanziiert und konfiguriert, um all die wesentlichen Mapping-Arbeiten durchzuführen.

Hier ist ein Beispiel für die Anwendung IoC AutoMapper (die Instantiierung des MappingEngine erfordert)

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

34

Ja, es gibt eine Möglichkeit, eine Instanz Version von AutoMapper zu verwenden.

Statt ...

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

können Sie:

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

Ich weiß nichts über ältere Versionen von AutoMapper, aber in der aktuellen Version heißt die 'Configuration' Klasse' ConfigurationStore'. –

+2

Und die 'AllMappers()' Methode ist jetzt eine Eigenschaft namens 'Mapper'. – bugged87

13

Als Reaktion auf Luke Woodwards ‚s comment auf der neueren Syntax:

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>();