Ich hatte einige echte Probleme mit automapper. Ich denke, ich habe die Lösung gefunden, aber unsicher, wie es zu implementieren.
Grundsätzlich verwende ich eine benutzerdefinierte Zuordnung mit ResolveUsing und ConstructedBy, um Parameter an den Konstruktor zu übergeben. Ich verstehe, dass die meisten Leute dies einmal in der global.asax einrichten und dann vergessen.
Aber das Problem ist, dass meine Methode (auf einem wcf) in verschiedenen Parametern an den Konstruktor eines ResolveUsing ...... übergibt
Vorher habe ich Mapper.CreateMap und Mapper.Map verwendet, die statische Methoden sind, und es scheint, dass sie miteinander in Konflikt geraten, wenn verschiedene Petitionen über Methoden (Multi-User) in den wcf-Dienst kommen.
Nachdem ich etwas gelesen habe, scheint es, dass ich die Instanzversion von CreateMap und Map verwenden kann, so dass jede einzelne Petition ihre eigene Karte erhält und ihre eigenen Parameter übergeben kann.
Aber ich kann nicht herausfinden, wie man das macht. Kann mir das bitte jemand erklären? Ich stecke wirklich fest...
Früher habe ich hin und wieder Fehler bei doppelten Schlüsseln bekommen, und ich habe auch einen Log-Trace auf den Konstruktor gelegt, und es scheint, dass eine Petition die andere überschreibt - daher die statischen Versionen von Mapper.
Ich hoffe, dass ich richtig liege, aber ich kann nichts anderes finden...
BEARBEITET - EIN BEISPIEL FÜR DAS, WAS ICH HABE
Grundsätzlich funktionieren alle Zuordnungen wie sie sollten, da ich in den meisten Fällen MapFrom verwende.
Dann erstelle ich eine Instanz meines Resolvers, die ich mit einer URL übergebe. Ich habe die URL überprüft, bevor ich sie übergebe, und sie ist korrekt. Aber sobald er zurückkehrt, gibt er die falsche URL zurück.
Der Grund, warum ich in der URL übergeben müssen ist, dass es Variablen in dort hat, so dass ich die Variablen ersetzt werden müssen ... Grundsätzlich gibt es 2 URLs je nach Büro und ich habe Protokolle überall und ich kann sehen, was ich in übergeben, aber sobald ich es in übergeben - es ist nicht die, die ich in übergeben, wenn das Sinn macht, das ist seltsam!!!
Es handelt sich um einen WCF-Dienst, und ein Client hat die Methode zweimal aufgerufen und dabei 2 verschiedene Büros und damit 2 verschiedene URLs angegeben. Aber sie geben immer die gleiche URL zurück. Es ist wie eine Sitzung überschreibt die andere...
Ich hoffe, das ist sinnvoll.
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 ES SCHEITERT - ABER UNBEKANNT WARUM
Siehe meine Kommentare inline mit dem Code. Im Konstruktor kommt das urlTemplate an, ich speichere es in einer privaten Var und im überschriebenen ResolveCore ist es dann etwas anderes :-)
Ich habe einige log4net-Protokolle dort abgelegt, 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
VORÜBERGEHENDE LÖSUNG
Ich habe eine vorläufige Lösung gefunden, aber sie ist wirklich schlecht. Ich bin sicher, automapper tun können, was ich versuche, aber ich bin offensichtlich etwas falsch machen.
Grundsätzlich gebe ich über LINQ eine Sammlung von Datensätzen zurück (DIES IST MEINE QUELLE), so dass ich ein neues Feld für jeden Datensatz eingegeben habe, der die richtige URL-Vorlage enthält. Und dann, anstatt in (über Konstruktor) die URL-Vorlage zu übergeben, habe ich es als eine Eigenschaft auf JEDEN Datensatz in der Sammlung (DIE QUELLE) verfügbar ... und es funktioniert perfekt.
Natürlich ist das wirklich ein Flickwerk und nicht ideal, aber es bringt mich zum Laufen.
Was mache ich falsch?
0 Stimmen
In Ihrem Beispiel ist es so, dass Sie die Quelle bis zur Laufzeit nicht kennen, aber Sie wissen, welches Ziel Sie zur Kompilierungszeit zuordnen?
0 Stimmen
Nein, ich kenne die Quelle ... aber ich bin in Variablen zu ResolveUsing mit Konstruktor daher die Karte muss jedes Mal erstellt werden und muss nicht von einer anderen Sitzung usw. geteilt werden übergeben
0 Stimmen
Wenn es sich um einen WCF-Dienst handelt, wird er in seiner eigenen Anwendungsdomäne ausgeführt, so dass die Maps nicht mit anderen Prozessen geteilt werden. Es klingt wie die Argumente zu ResolveUsing variieren, aber ResolveUsing nimmt den Quelltyp in der Regel. Was ist der Grund dafür, dass Sie Argumente in den Konstruktor Ihres benutzerdefinierten Value Resolver übergeben, die außerhalb Ihres Quelltyps sind?
0 Stimmen
Hallo danke für das Erhalten zurück zu mir, gut zum Beispiel ich bin in RentalDays (Anzahl der Miettage) als seine nicht in der Quelle übergeben, wie ich dies in meinem ResolveUsing verwenden müssen.
0 Stimmen
Der andere Typ, den ich tue, ist die Übergabe einer Liste an einen Resolver, um eine Liste an die src zurückzugeben? warum? weil die Liste eine Sammlung von Zeichenfolgen ist, aber die Zeichenfolgen enthalten Variablen so meine resolveusing ersetzt die Variablen mit realen Werten und baut die Liste, um es an die Quelle zurückzugeben neu auf.
0 Stimmen
Kann ich zusätzliche Informationen bereitstellen - bitte lassen Sie es mich wissen?
0 Stimmen
In Bezug auf die Miettage, das wird seltsam klingen!! ich weiß ... aber ich habe Protokolle eingerichtet (log4net). ich verwende eine lokale Variable, die rentaldays (zum Beispiel) ist = 2 und ich übergebe es in der resolveusing in den contructor der Methode, die ich auf resolveusing Ich habe ein anderes Protokoll platziert, um den Wert von dem, was es übergeben wird, und es ist = 1 ausdrucken!!! Ja, ich weiß, seltsam... die anderen Sitzungen haben diesen Wert auf 1 gesetzt... also nehme ich an, dass es überschrieben wird oder so... Das ist meine Synatax.. opt.ResolveUsing<CalculatePriceResolver>().ConstructedBy(() => new CalculatePriceResolver(realRentalDays)
0 Stimmen
Ausgehend von dem, was ich hier sehe, haben Sie einen Dienst CalculatePriceService, der zur Berechnung eines Preises auf der Grundlage der realRentalDays verwendet wird. Ich denke, dass Sie vielleicht nicht AutoMapper dafür verwenden möchten, sondern dies vielleicht als einen Schritt in Ihrem WCF-Dienst haben, der den Wert außerhalb des Mappings berechnet. Normalerweise verwende ich das Mapping, um Werte von einem Typ auf einen anderen abzubilden oder Objekthierarchien zu verflachen. Dies gehört vielleicht nicht in den Mapping-Prozess.
0 Stimmen
Okay Michael, danke! Guter Punkt - ok, ich werde versuchen, es aus.... zu verschieben und in eine Art Standardmethode zu integrieren. Das Problem ist, dass der Preis "METHOD" auf die Eigenschaft Preis, die in meinem "SRC" Mapping-Objekt ist angewiesen ist.