Heim > Artikel > Backend-Entwicklung > Verwenden Sie AutoMapper, um eine kostenlose Konvertierung zwischen Dto und Model zu erreichen (Teil 2)
Das Buch wird von oben fortgeführt. Im vorherigen Artikel haben wir zwei Möglichkeiten besprochen, AutoMapper zum Implementieren einer 1:1-Zuordnung zwischen Typen zu verwenden – Konvention und Konfiguration – und gelernt, wie man eine einfache OO-Zuordnung durchführt. Im letzten Artikel dieser Serie möchte ich einige Themen auf mittlerer Ebene basierend auf unseren Anforderungen diskutieren, darunter: wie man die Zuordnung zwischen Typkörpertypen implementiert und wie man mehrere Zuordnungsregeln für zwei Typen implementiert.
【4】Ordnen Sie einen Typ einem Typsystem zu.
Sehen Sie sich zunächst unser Dto und unser Modell an. Wir haben BookDto, wir haben Author und jeder Autor hat seine eigene ContactInfo. Nun eine Frage: Wie bekomme ich das Author-Objekt des Erstautors von BookDto? Die Antwort ist einfach, aber nicht einfach.
Der einfachste Weg besteht darin, das zuvor erwähnte CountructUsing zu verwenden, um die Zuordnung aller Felder und Untertypfelder von BookDto zu Author anzugeben:
C#-Code
var map = Mapper. CreateMap & lt; bookDTO, Autor & gt; (); FirstAuthorBlog,
🎜>
Dieser Ansatz kann funktionieren, ist aber sehr unwirtschaftlich. Da wir die Zuordnung von BookDto zu Author von Grund auf durchführen und die Zuordnung von BookDto zu ContactInfo bereits implementiert wurde, besteht eigentlich keine Notwendigkeit, sie erneut zu schreiben. Stellen Sie sich vor, wenn es einen anderen Reader-Typ gibt, der auch ContactInfo enthält, sollten wir beim Zuordnen von BookDto zu Reader die Logik BookDto -> ContactInfo erneut schreiben? Stellen Sie sich noch einmal vor, wenn wir die Zuordnung von BookDto zu Book implementieren, müssen wir dann die Zuordnungsregeln von BookDto zu Author erneut schreiben?
Ich denke daher, dass für diese Art der Zuordnung zwischen Typsystemen der ideale Ansatz darin besteht, für jeden spezifischen Typ eine einfache Zuordnung anzugeben und dann die Zuordnung des einfachen Typs bei der Zuordnung komplexer Typen wiederzuverwenden. Beschreiben Sie es in einfacherer Sprache:
Wir haben vier Typen A, B, C und D, wobei B = [C, D]. Gegeben sei A ->
Meine Lösung besteht darin, den von AutoMapper bereitgestellten IValueResolver zu verwenden. IValueResolver ist ein von AutoMapper definierter Typ zur Implementierung spezifischer Zuordnungslogik auf Feldebene. Seine Definition lautet wie folgt:
C#-Code
öffentliche Schnittstelle IValueResolver
{
ResolutionResult Resolve(ResolutionResult source);
}
In tatsächlichen Anwendungen verwenden wir häufig seine generische Unterklasse – ValueResolver, und implementieren diese abstrakte Methode:
C#-Code
protected abstract TDestination ResolveCore(TSource source);
wobei TSource der Quelltyp und TDestination der Zieltyp ist.
Zurück zu unserem Beispiel, wir können BookDto jetzt wie folgt zuordnen -> Autor:
C#-Code
var map = Mapper.CreateMap
map.ForMember(d => d.Name, opt => opt.MapFrom(s => s.FirstAuthorName))
.ForMember(d => d .Description, opt => opt.MapFrom(s => s.FirstAuthorDescription))
.ForMember(d => d.ContactInfo,
opt => opt. ResolveUsing< ;FirstAuthorContactInfoResolver>()));
In FirstAuthorContactInfoResolver implementieren wir ValueResolver und verwenden BookDto -> ContactInfo-Logik:
C#-Code
öffentliche Klasse FirstAuthorContactInfoResolver : ValueResolver
}
}
Alles ist erledigt.Ähnlich können wir jetzt BookDto -> Book implementieren, oder? Durch die Wiederverwendung von BookDto -> Author und BookDto ->
Ist es wirklich möglich? Es scheint immer noch ein Problem zu geben. Ja, wir werden feststellen, dass wir BookDto zwei verschiedenen Autoren zuordnen müssen und ihre Feldzuordnungsregeln unterschiedlich sind. was zu tun? Kommen wir schnell zu unserem letzten Thema.【5】Implementieren mehrerer Sätze von Zuordnungsregeln für zwei Typen
Unser Problem ist: Für die Typen A und B müssen wir zwei verschiedene A -> B definieren und zulassen, dass sie gleichzeitig verwendet werden. Tatsächlich bietet der aktuelle AutoMapper hierfür keine vorgefertigte Möglichkeit.Natürlich können wir die Methode „Kurve zur Rettung des Landes“ verwenden – definieren Sie zwei Unterklassen von Autor für den ersten Autor und den zweiten Autor, wie z. B. FirstAuthor und SecondAuthor, und implementieren Sie dann BookDto –> > SecondAuthor-Zuordnung. Allerdings ist diese Methode auch nicht sehr wirtschaftlich. Was ist, wenn es einen dritten Autor oder sogar einen vierten Autor gibt? Für jeden Autor eine Unterklasse „Autor“ definieren?
Andererseits könnten wir genauso gut davon ausgehen, dass, wenn AutoMapper eine solche Funktion bereitstellen würde, wie sie aussehen würde? Die CreateMap-Methode und die Map-Methode sollten wie folgt definiert werden:
C#-Code
CreateMap
Map
Wenn wir es verwenden, können wir:
C#-Code var firstAuthorMap = Mapper.CreateMap// Definiere BookDto -> Autorenregel
var firstAuthor = Mapper.Map
var secondAuthor = Mapper.Map
MappingEngine ist die Mapping-Ausführungs-Engine von AutoMapper. Wenn wir Mapper.CreateMap aufrufen, schreiben wir Regeln in die Konfiguration, die dieser Standard-MappingEngine entsprechen Bei Objekten wird die Standard-MappingEngine verwendet, um die Regeln in der entsprechenden Konfiguration auszuführen.
Kurz gesagt, eine MappingEngine ist eine „virtuelle Maschine“ von AutoMapper. Wenn wir mehrere „virtuelle Maschinen“ gleichzeitig starten und unterschiedliche Zuordnungsregeln für dasselbe Typenpaar auf verschiedenen „virtuellen Maschinen“ festlegen, können Sie dies tun Lassen Sie sie ruhig laufen, wenn Sie sie verwenden, fragen Sie einfach die entsprechende „virtuelle Maschine“, welche Regel verwendet werden soll.Tu es einfach. Zuerst definieren wir eine MappingEngineProvider-Klasse und verwenden sie, um verschiedene MappingEngines zu erhalten:
C#-Code
öffentliche Klasse MappingEngineProvider
{
private readonly MappingEngine _engine;
public MappingEngine Get()
{ >
}Wir abstrahieren verschiedene Arten von Zuordnungsregeln in Interface-IMapping :
C#-Code public interface IMapping {
void AddTo(Configuration config);
Fügen Sie dann die erforderlichen Regeln in die entsprechende MappingEngine im Konstruktor von MappingEngineProvider ein:
C#-Code private static Dictionary
public MappingEngineProvider(Engine engine)
Beachten Sie, dass wir einen Aufzählungstyp Engine verwendet haben, um mögliche MappingEngines zu identifizieren:
C#-Codepublic enum Engine { Basic = 0, First,
Second
Wir verwenden 3 Engines: „Basic“ dient zum Platzieren aller grundlegenden Zuordnungsregeln, „First“ wird zum Platzieren aller Dto->
Wir definieren außerdem ein Wörterbuch _rule, das alle Zuordnungsregeln platziert und die Regeln in verschiedene Engines klassifiziert.Das Einzige, was noch übrig bleibt, ist, die dictionary_rule mit unserer Zuordnung auszufüllen. Zum Beispiel fügen wir BookDtoToFirstAuthorMapping in die erste Engine und BookDtoToSecondAuthorMapping in die zweite Engine ein:
C#-Code private static readonly Dictionaryneues Wörterbuch
new BookDtoToFirstAuthorMapping(),
}
> { Verschiedene MappingEngineProvider-Objekte können im Voraus instanziiert werden:
C#-Code public static SimpleMappingEngineProvider First = new MappingEngineProvider(Engine.First); public static SimpleMappingEngineProvider Second = new MappingEngineProvider(Engine.Second);Jetzt können wir diese 2 Engines verwenden Gleichzeitig beim Zuordnen von BookDto -> Book, um 2 Autoren zu erhalten und sie im Feld „Autoren“ zusammenzustellen:
C#-Code öffentliche Klasse BookDtoToBookMapping: DefaultMapping{
protected override void MapMembers(IM applyExpression< ;BookDto, Book> map)
{
map.ForMember(d => d.Authors ,
opt => op t.ResolveUsing
: Secondauthor.isnull ()
: neue Liste
Second.Get()},
kann auch so sein:
C#-Code var book = MyMapper.MapPostscript: Ich habe festgestellt, dass das Hochladen von Dateien auf Github zu Hause extrem langsam war, also habe ich beschlossen, zuerst meinen Code zu packen und hochzuladen. Jeder kann gerne darauf zurückgreifen.