ahhay
ahhay | Hinter den Höfen 20 | 37339 Haynrode/Germany | 036077 935077

C# und AutoMapper


Wie kann man zwei Objekte ineinander abbilden?

In vielen Anwendungen müssen Objekte zwischen Presentation(UI)-, Application- und Domainschicht oder Dienstleistung zugeordnet werden. Die zeitaufwendige Abbildung der Objekte zwischen den einzelnen Schichten ist sehr hektisch. Es gibt von hausaus keine einfachen und schnellen Mechanismen, um zwei Objekte ineinander abzubilden. Um diese Problematik zu umgehen kann man AutoMapper Klassen verwenden, welche die Eigenschaften zwischen zwei Objekten automatisch zuordnen. Diese Klassen bieten auch die Option benutzerdefiniertes Mapping auszuführen.

Was ist ein AutoMapper?

AutoMapper mappt (findet die Verbindung, identische Eigenschaften und bildet diese aufeinander ab) zwischen zwei Objekten. Beim Automapper werden zwei verschiedene Einheiten (Objekte) durch die Umwandlung eines Eingangsobjektes des einen Typs zu einem Ausgangsobjekt eines anderen Typs abgebildet. Diese Mapper-Klasse kann überall eingesetzt werden, aber im Allgemeinen ist es beim Mappen von Einheiten der UI-Schicht zur Domain- oder Serviceschicht präsent.

Mit dem AutoMapper werden lästige und fehleranfällige Konventionen elegant gelöscht. Aber nicht nur das, zudem wird eine manuelle Zuordnung der richtigen Parameter vorgenommen.

Wie und wo kann der AutoMapper gedownload werden?

AutoMapper ist als Open-Source-Bibliothek in GitHub vorhanden. Die entsprechende Bibliothek kann über den NuGet Package Manager zu Ihrem Visual Studio-Projekt hinzugefügt werden. Oder direkt über die NuGet-Konsole. Dort gibt man den folgenden Befehl, um die AutoMapper Bibliothek zu installieren:

PM> Install-Package AutoMapper

Wie wird der AutoMapper eingesetzt?

Der AutoMapper kann in einem Projekt auf viele Arten verwendet werden. Um mehr Informationen zu erhalten kann man auch "Erste Schritte" von GitHub besuchen. In diesem Beitrag werden die vielseitigen Anwendungsmöglichkeiten der Bibliothek grob vorgestellt.
Es handelt sich um ein klassisches Beispiel mit zwei Klassen mit dem Namen "Person" und "Mitarbeiter". Diese zwei unterschiedlichen Einheiten haben einige Eigenschaften gemeinsam, die Mitarbeiter-Klasse hat aber eine zusätzliche Eigenschaft.

Im folgenden Code-Snipper, kann man sehen, dass die Person-Klasse vier Eigenschaften (Vorname, Nachname, Adresse und Kontakt) besitzt. Die Mitarbeiter-Klasse hat eine zusätzliche Eigenschaft mit dem Namen Name, welche eine zusammengesetzte Eigenschaft ist.

In der Beispielsolution sollen die Objekte der Klasse "Person" in Objekte der Klasse "Mitarbeiter" gespeichert werden. Die AutoMapper-DLL ist als Assembly Referenz im Projekt bereits installiert. Für diesen Anwendungsfall wird die ToString()-Methode der Mitarbeiter-Klasse überschrieben. Somit können wir die ToString()-Methode auf dem Objekt aufrufen und so die Werte seiner Eigenschaften in angemessener Weise zurückgeben.

Dies ist der komplette Code-Schnipsel aus der Beispielsolution:
public class Mitarbeiter 
{
    public string Vorname { get; set; }
    public string Nachname { get; set; }
    public string Name { get; set; }
    public string Adresse { get; set; }
    public string Kontakt { get; set; }
}
                            

Im ersten Ansatz soll das Mapping auf dem Standardweg genutzt werden. Die beiden Objekte werden 1:1 gemappt.
private void HandleMappingStandard()
{
    _ma = new Mitarbeiter();
    _ma.Vorname = PersonDaten.Vorname;
    _ma.Nachname = PersonDaten.Nachname;
    _ma.Name = PersonDaten.Vorname + " " + PersonDaten.Nachname;
    _ma.Adresse = PersonDaten.Adresse;
    _ma.Kontakt = PersonDaten.Kontakt;
    MitarbeiterDaten.Add(_ma);
}
                            

Die zweite Methode benutzt die AutoMapper-Klassen. Alle Zuordnungen erfolgen automatisch anhand der Eigenschaftsnamen (Vorname, Nachname, Adresse und Kontakt). Die Name-Eigenschaft der Mitarbeiter-Klasse ist keine entsprechende Eigenschaft in der Person-Klasse und kann demzufolge nicht zugeordnet werden.
Um die Standardzuordnung zu erstellen, ruft man die Mapper.CreateMap<T1, T2>() mit den richtigen Typen auf. In diesem Fall entspricht T1 den Person-Objekten und T2 den Mitarbeiter-Objekten. Im nachfolgenden Code-Schnipsel findet man die Implementierung des Standard-Mapping:

private void HandleMappingAutoMapper()
{
    _ma = new Mitarbeiter();

    _ma = Mapper.Map<person, mitarbeiter>(PersonDaten);

    MitarbeiterDaten.Add(_ma);
}
                            

Die Klasse Mapper.Map<T1, T2>() nimmt Objekt T1 um dieses dem Objekt T2 zuzuordnen. Nun werden die Eigenschaften des Person-Objektes in die gleichnamigen Eigenschaften des Mitarbeiter-Objektes gedruckt. Das kann bei allen Eigenschaften außer Name erfolgen. In der Beispielsolution kann man das Ergebnis betrachten.
Im nächsten Schritt wird der Vorgang des Mapping ein wenig komplexer. Hier wird eine benutzerdefinierte Zuordnung zwischen zwei Objekten Person und Mitarbeiter geschaffen. Für diesen Vorgangen können die AutoMapper-Methoden ForMember() und MapFrom() genutzt werden. Dies wird im folgenden Code-Schnipsel dargestellt:

private void HandleMappingCustomer()
{
    _ma = new Mitarbeiter();

    Mapper.CreateMap<person, mitarbeiter>().ForMember(emp => emp.Name,
        map => map.MapFrom(p => p.Vorname + " " + p.Nachname));
        
    _ma = Mapper.Map<person, mitarbeiter>(PersonDaten);
        
    MitarbeiterDaten.Add(_ma);
}
                            

Es erfolgt die bekannte Zuordnung der gleichnamigen Eigenschaften der beiden Objekte und zusätzlich wird Eigenschaft "Name" der Mitarbeiter-Klasse mit der verketteten Zeichenfolge von den Eigenschaften Vorname und Nachname, wie im oberen Code-Schnipsel beschrieben, zugeordnet. Nach Betätigung des Buttons der Beispielsolution kann man sehen, dass die Eigenschaft "Name" des Mitarbeiter-Objektes automatisch mit Vorname und Nachname gefüllt ist. Ausgabe der oben genannten Codebeispiele (sowohl Standard- als auch kundenspezifischen Mapping):