wake-up-neo.com

AutoMapper vs ValueInjecter

Jedes Mal, wenn ich nach AutoMapper Material auf StackOverflow suche, lese ich etwas über ValueInjecter .

Kann mir jemand die Vor- und Nachteile erklären (Leistung, Funktionen, API-Nutzung, Erweiterbarkeit, Testen)?

209
Rookian

als Schöpfer von ValueInjecter kann ich Ihnen sagen, dass ich es getan habe, weil ich etwas einfaches und sehr flexibles wollte.

Ich schreibe wirklich nicht viel oder viel monkey code Wie:

Prop1.Ignore, Prop2.Ignore etc.
CreateMap<Foo,Bar>(); CreateMap<Tomato, Potato>(); etc.

ValueInjecter ist etwas wie Mozilla mit seinen Plugins. Sie erstellen ValueInjections und verwenden sie

es gibt integrierte Injektionen zum Abflachen und Aufheben der Abflachung sowie einige, die vererbt werden sollen

und es funktioniert mehr in einer Art Aspekt , Sie müssen nicht alle Eigenschaften 1-zu-1 angeben, sondern Sie tun etwas wie:

Nimm alle int-Eigenschaften von der Quelle, deren Name mit "Id" endet, transformiere den Wert und setze jede Eigenschaft im Quellobjekt mit demselben Namen ohne das Id-Suffix und ihr Typ wird von Entity geerbt, so etwas

also ein offensichtlicher Unterschied, ValueInjecter wird auch in Windows-Formularen mit und ohne Reduzierung verwendet, so flexibel ist es

(Zuordnung vom Objekt zum Formularsteuerelement und zurück)

Automapper, der nicht in Windows Forms verwendet werden kann, kein Unflatenning, aber es enthält nützliche Funktionen wie das Zuordnen von Sammlungen. Wenn Sie es also mit ValueInjecter benötigen, tun Sie einfach Folgendes:

foos.Select(o => new Bar().InjectFrom(o));

sie können ValueInjecter auch zum Zuordnen von anonymen und dynamischen Objekten verwenden

Unterschiede:

  • automapper Konfigurationserstellung für jede Zuordnungsmöglichkeit CreateMap ()

  • valueinjecter injiziert von jedem Objekt zu jedem Objekt (es gibt auch Fälle, in denen Sie von Objekt zu valueetype injizieren)

  • automapper hat eine Reduzierung erstellt, und zwar nur für einfache Typen oder für Typen desselben Typs, und die Reduzierung wird nicht aufgehoben

  • valueinjecter nur wenn Sie es brauchen Sie tun target.InjectFrom<FlatLoopValueInjection>(source); also <UnflatLoopValueInjection> und wenn Sie von Foo.Bar.Name of type String zu FooBarName of type Class1 wollen, erben Sie FlatLoopValueInjection und geben dies an

  • automapper ordnet standardmäßig Eigenschaften mit demselben Namen zu. Im Übrigen müssen Sie die Eigenschaften einzeln angeben und Aufgaben wie Prop1.Ignore (), Prop2.Ignore () usw. ausführen.

  • valueinjecter verfügt über eine Standardinjektion .InjectFrom (), die die Eigenschaften mit demselben Namen und Typ ausführt. für alles andere erstellen Sie Ihre benutzerdefinierten Werteinjektionen mit individuellen Zuordnungslogiken/-regeln, eher wie Aspekte, z. von allen Requisiten vom Typ Foo bis zu allen Requisiten vom Typ Bar

170
Omu

Da ich noch nie eines der anderen Tools verwendet habe, kann ich nur über AutoMapper sprechen. Ich hatte ein paar Ziele für die Erstellung von AutoMapper:

  • Unterstützt das Abflachen von DTO-Objekten
  • Unterstützung offensichtlicher Szenarien (Sammlungen, Aufzählungen usw.)
  • In der Lage sein, Zuordnungen in einem Test leicht zu überprüfen
  • Lassen Sie Edge-Fälle zu, um Werte von anderen Stellen aufzulösen (benutzerdefinierte Typ-> Typzuordnung, Zuordnung einzelner Elemente und einige wirklich verrückte Edge-Fälle).

Wenn Sie diese Dinge tun möchten, funktioniert AutoMapper sehr gut für Sie. Was AutoMapper nicht gut macht, sind:

  • Vorhandene Objekte füllen
  • Abflachen

Der Grund dafür ist, dass ich diese Dinge nie tun musste. In den meisten Fällen haben unsere Entitäten keine Setter, machen keine Sammlungen verfügbar usw. Deshalb ist es nicht da. Wir verwenden AutoMapper zum Reduzieren auf DTOs und zum Zuordnen von UI-Modellen zu Befehlsnachrichten und dergleichen. Hier funktioniert es wirklich sehr, sehr gut für uns.

59
Jimmy Bogard

Ich habe beides ausprobiert und bevorzuge ValueInjecter, weil es so einfach ist:

myObject.InjectFrom(otherObject);

Das ist alles, was ich für den Großteil meines Injektionsbedarfs wissen muss. Einfacher und eleganter geht es kaum.

55
Adrian Grigore

Dies ist eine Frage, die ich auch recherchiert habe, und für meinen Anwendungsfall scheint es sich um eine Frage zu handeln, die zweifellos von Wert ist. Für die Verwendung ist keine vorherige Einrichtung erforderlich (dies kann die Leistung beeinträchtigen, obwohl bei einer intelligenten Implementierung die Zuordnungen für zukünftige Aufrufe zwischengespeichert werden könnten, anstatt sie jedes Mal wiederzugeben). Sie müssen also keine Zuordnungen vordefinieren, bevor Sie sie verwenden.

Am wichtigsten ist jedoch, dass eine umgekehrte Zuordnung möglich ist. Jetzt kann ich hier etwas vermissen, da Jimmy erwähnt, dass er keinen Anwendungsfall sieht, in dem dies notwendig ist. Vielleicht habe ich das Muster falsch, aber mein Anwendungsfall ist, dass ich ein ViewModel-Objekt aus meinem ORM erstelle. Ich zeige dies dann auf meiner Webseite an. Wenn der Benutzer fertig ist, wird das ViewModel wieder als httppost angezeigt. Wie wird es in die ursprünglichen ORM-Klassen konvertiert? Ich würde gerne das Muster mit automapper kennen. Mit ValueInjector ist es trivial, und es wird sogar abgeflacht. z. B. Erstellen einer neuen Entität

Das vom Entityframework erstellte Modell (Modell zuerst):

public partial class Family
{ 
    public int Id { get; set; }
    public string FamilyName { get; set; }

    public virtual Address Address { get; set; }
}

public partial class Address
{
    public int Id { get; set; }
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string TownCity { get; set; }
    public string County { get; set; }
    public string Postcode { get; set; }

    public virtual Family Family { get; set; }
}

Das ViewModel (das ich mit Validatoren dekorieren kann):

public class FamilyViewModel
{
    public int Id { get; set; }
    public string FamilyName { get; set; }

    public int AddressId { get; set; }
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string AddressTownCity { get; set; }
    public string AddressCounty { get; set; }
    public string AddressPostcode { get; set; }
}

Der ViewController:

    //
    // GET: /Family/Create

    public ActionResult Create()
    {
        return View();
    } 

    //
    // POST: /Family/Create

    [HttpPost]
    public ActionResult Create(FamilyViewModel familyViewModel)
    {
        try
        {
            Family family = new Family();
            family.InjectFrom<UnflatLoopValueInjection>(familyViewModel);
            db.Families.Add(family);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        catch
        {
            return View();
        }
    }

Einfacher geht es meiner Meinung nach nicht?

(Das wirft also die Frage auf, was mit dem Muster, auf das ich stoße (und das scheinen viele andere zu tun), falsch ist, dass es für AutoMapper nicht als Wert angesehen wird?)

Wenn dieses Muster jedoch wie beschrieben verwendet werden soll, ist meine Stimme ein Wert, der von einer Landmeile abweicht.

27
DanH