AutoMapper vs ValueInjecter [chiuso]


209

Ogni volta che sto cercando materiale AutoMapper su StackOverflow, sto leggendo qualcosa su ValueInjecter .

Qualcuno può dirmi i pro e i contro (prestazioni, funzionalità, utilizzo dell'API, estensibilità, test)?


2
Un altro che vedo menzionato molto è EmitMapper .
adrianbanks,

1
E la colla? glue.codeplex.com Sembra anche un grande progetto, ma non l'ho ancora provato. Lo farò durante il prossimo mese però. Ho anche visto un progetto chiamato EmitMapper emitmapper.codeplex.com
Trygve

Vedi un articolo che parla di questi due strumenti - devproconnections.com/development/…
George Birbilis,

Risposte:


170

come creatore di ValueInjecter , posso dirti che l'ho fatto perché volevo qualcosa di semplice e molto flessibile

Non mi piace davvero molto scrivere o scrivere molti monkey codesimili:

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

ValueInjecter è qualcosa come mozilla con i suoi plugin, crei ValueInjections e li usi

ci sono iniezioni incorporate per l'appiattimento, non appiattimento e alcune che sono destinate ad essere ereditate

e funziona più in un tipo di aspetto , non è necessario specificare tutte le proprietà da 1 a 1, invece fai qualcosa del tipo:

prende tutte le proprietà int dalla sorgente il cui nome termina con "Id", trasforma il valore e imposta ciascuna su una proprietà nell'oggetto sorgente con lo stesso nome senza il suffisso Id e il suo tipo è ereditato da Entity, cose del genere

quindi un'ovvia differenza, ValueInjecter viene utilizzato anche in forme Windows con appiattimento e non appiattimento, ecco quanto è flessibile

(mappatura da oggetto a controlli forma e ritorno)

Automapper, non utilizzabile in Windows Form, senza appiattire, ma ha buone cose come la mappatura delle raccolte, quindi nel caso in cui tu ne abbia bisogno con ValueInjecter fai semplicemente qualcosa del tipo:

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

puoi anche usare ValueInjecter per mappare da oggetti anonimi e dinamici

differenze:

  • automapper crea la configurazione per ogni possibilità di mappatura CreateMap ()

  • valueinjecter inietta da qualsiasi oggetto a qualsiasi oggetto (ci sono anche casi in cui si inietta da oggetto a tipo di valore)

  • automapper lo ha appiattito, e solo per tipi semplici o dello stesso tipo, e non ha appiattimento

  • valueinjecter solo se avete bisogno di fare target.InjectFrom<FlatLoopValueInjection>(source); also <UnflatLoopValueInjection> e se si vuole da Foo.Bar.Name of type Stringa FooBarName of type Class1si eredita FlatLoopValueInjection e specifica questa

  • automapper mappa le proprietà con lo stesso nome per impostazione predefinita e per il resto devi specificare una per una e fare cose come Prop1.Ignore (), Prop2.Ignore () ecc.

  • valueinjecter ha un'iniezione predefinita .InjectFrom () che esegue le proprietà con lo stesso nome e tipo; per tutto il resto crei le tue scelte di valore personalizzate con singole logiche / regole di mappatura, più aspetti simili, ad esempio da tutti gli oggetti di scena di tipo Foo a tutti gli oggetti di scena di tipo Bar


5
Per il dio dell'amore per favore dimmi che ValueInjector può prendere un grafico profondo ViewModel e mappare a / da un grafico profondo Entità aziendale e mappare tutto ciò che è esattamente lo stesso senza lavoro, e che ho solo bisogno di specificare come gestire ciò che è diverso. Speravo che AutoMapper aggiungesse questa funzionalità ma non si è mai materializzato e non ho avuto il tempo di scrivere il mio auto mapper.
Chris Marisic,

3
@Chris Marisic puoi usarlo, nel caso in cui intendi la clonazione profonda, ho fatto un'iniezione una volta che in qualche modo lo fa in modo ricorsivo ma non funziona per le proprietà delle collezioni valueinjecter.codeplex.com/Thread/View.aspx?ThreadId=236126 , oppure puoi fare un Flat ViewModel e usare l'appiattimento e l'appiattimento, questo sarebbe facile
Omu,

ViewModel e Domain Entities sarebbero simili ma diversi, quindi non un puro clone. Il 90% delle proprietà sono in genere il tipo e il nome esatti, i ViewModels spesso finiscono con SelectLists e cose legate a loro che vorrei ignorare tornando al dominio. Tuttavia, è molto probabile che entrambi abbiano raccolte di oggetti.
Chris Marisic,

27
<pedant>Sembra bello, ma forse dovrebbe essere ValueInjectOr? </pedant>
Craig Stuntz,

1
ma per qualche ragione è così :)
Omu,

59

Dato che non ho mai usato nessuno degli altri strumenti, posso solo parlare di AutoMapper. Avevo in mente alcuni obiettivi per la creazione di AutoMapper:

  • Supporta l'appiattimento di oggetti DTO stupidi
  • Supporta scenari ovvi pronti all'uso (raccolte, enumerazioni ecc.)
  • Essere in grado di verificare facilmente i mapping in un test
  • Consenti casi limite per la risoluzione di valori da altri luoghi (tipo personalizzato-> mappatura dei tipi, mappatura dei singoli membri e alcuni casi limite davvero pazzi).

Se vuoi fare queste cose, AutoMapper funziona molto bene per te. Le cose che AutoMapper non fa bene sono:

  • Riempimento di oggetti esistenti
  • Unflattening

Il motivo è che non ho mai avuto bisogno di fare queste cose. Per la maggior parte, le nostre entità non hanno setter, non espongono raccolte, ecc. Ecco perché non è lì. Usiamo AutoMapper per appiattire i DTO e mappare dai modelli UI per comandare messaggi e simili. Ecco dove funziona davvero, molto bene per noi.


1
@Jimmy Bogard Ritieni che il riempimento di oggetti esistenti sia mai arrivato all'elenco delle funzionalità di AutoMapper?
Romano

Non ho provato ValueInjecter, ma per ciò di cui abbiamo bisogno, automapper è molto potente.
richb01

Penso che la cosa più importante qui sia la verificabilità. Nel rinominare e riformattare le cose questo è di grande aiuto.
Kugel,

55

Ho provato entrambi e preferisco ValueInjecter perché è così semplice:

myObject.InjectFrom(otherObject);

Questo è tutto ciò che c'è da sapere per la stragrande maggioranza delle mie esigenze di iniezione. Non può essere più semplice ed elegante di così.


1
this objectmetodo di estensione lì?
Chris Marisic,

2
Come posso disaccoppiare il mio codice da ValueInjecter? Per me sembra che abbia sempre una dipendenza da ValueInjecter, cioè nel mio progetto web, perché uso ValueInjecter (metodo di estensione) sull'oggetto dato DIRETTAMENTE.
Rookian,

1
@Rookian onestamente questa non è una preoccupazione che dovresti pensare troppo. Potresti dipendere dall'interfaccia come menzionato @Omu, quindi se cambi i mapper potresti risparmiare un po 'di lavoro (probabilmente non molto). Questo tipo di dipendenza è troppo difficile da sottrarre a meno che tu non voglia entrare in pieno AOP che è sfortunatamente molte volte semplicemente annullabile poiché .NET non aiuta a fornire correttamente il supporto AOP. Ora è possibile rimuovere AOP parte del mapping, soprattutto se si utilizza MVC e si scrivono filtri di azione che gestiscono il mapping ViewModel / DomainModel.
Chris Marisic,

13
perché un wrapper è la soluzione migliore? L'unica cosa che devi fare se vuoi cambiare mapper è implementare il InjectFrom()metodo di estensione da solo.
Jgauffin,

1
Ho provato anche entrambi e preferisco AutoMapper. L'ho usato per una piccola parte del mio sistema in cui associo entità con classi generate da Linq2Sql. Mappatura semplice come StockTotalQuantity -> stock_size_quantity o UserId -> user_id ha funzionato con AutoMapper per impostazione predefinita. Non ha funzionato con ValeInjecter anche dopo aver aggiunto la convinzione. Attenersi ad AutoMapper per ora.
Artur Kędzior,

27

Questa è una domanda che ho studiato anche io, e per il mio caso d'uso, sembra essere più conveniente. Non richiede alcuna configurazione precedente da utilizzare (potrebbe influire sulle prestazioni, immagino, anche se se implementato in modo intelligente potrebbe memorizzare nella cache i mapping per invocazioni future anziché riflettere ogni volta), quindi non è necessario predefinire alcun mapping prima di utilizzarli.

Ancora più importante, tuttavia, consente la mappatura inversa. Ora potrei mancare qualcosa qui mentre Jimmy menziona che non vede alcun caso d'uso dove è necessario, quindi forse ho lo schema sbagliato, ma il mio caso d'uso è che sto creando un oggetto ViewModel dal mio ORM. Poi lo visualizzo sulla mia pagina web. Una volta che l'utente termina, visualizzo nuovamente ViewModel come httppost, come viene riconvertito nelle classi ORM originali? Mi piacerebbe conoscere il modello con automapper. Con ValueInjector è banale e non si appiattisce. ad es. creazione di una nuova entità

Il modello creato da entityframework (prima il modello):

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

Il ViewModel (che posso decorare con i validatori):

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

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

Secondo me, non è molto più semplice di così?

(Quindi questo fa sorgere la domanda, cosa c'è di sbagliato nel modello in cui mi imbatto (e sembra che molti altri lo facciano), che non è visto come di valore per AutoMapper?)

Tuttavia, se questo schema, come descritto, è quello che vuoi usare, allora il mio voto è più prezioso di un miglio di campagna.


1
probabilmente dovresti anche porlo in una domanda separata taggata con asp.net-mvc e best practice, ViewModel ..., atm Non vedo alcun problema fintanto che funziona bene per te, ma sono sicuro che qualcuno potrebbe avere opinioni diverse
Omu,

Bene, ho imparato di più mvc. Ora posso rispondere alla mia domanda. Il modo per aggiornare il modello originale quando si ottiene indietro un modello di visualizzazione popolato consiste nell'utilizzare la funzione UpdateModel () fornita da mvc.
DanH,

1
UpdateModel () viene utilizzato per popolare il Modello che rappresenta la vista ed è lo stesso che fare Azione (modello MyModelClasss)
Omu

Vero, ma se si desidera avere un modello di vista separato per esempio un modello di repository, allora può essere usato per popolare che assumere la mappatura sia banale (e spesso lo è). Ovviamente se ValueInjector più complesso si presenta da solo.
DanH,

1
Penso che si possa sostenere che non dovresti semplicemente reimpostare le tue proprietà sul tuo modello di dominio, ma dovresti usare metodi che aggiungano significato ad esso.
Mike Cole,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.