AutoMapper vs ValueInjecter [ditutup]

209

Setiap kali saya mencari hal-hal AutoMapper di StackOverflow, saya membaca sesuatu tentang ValueInjecter .

Bisakah seseorang memberi tahu saya pro dan kontra di antara mereka (kinerja, fitur, penggunaan API, ekstensibilitas, pengujian)?

Rookian
sumber
2
Satu lagi yang saya lihat banyak disebutkan adalah EmitMapper .
adrianbank
1
Bagaimana dengan lem? lem.codeplex.com Sepertinya proyek yang bagus juga, tapi saya belum mencobanya. Saya akan selama bulan depan sekalipun. Saya juga melihat sebuah proyek bernama EmitMapper emitmapper.codeplex.com
Trygve
Lihat artikel yang berbicara tentang kedua alat tersebut - devproconnections.com/development/…
George Birbilis

Jawaban:

170

sebagai pencipta ValueInjecter , saya dapat memberitahu Anda bahwa saya melakukannya karena saya menginginkan sesuatu yang sederhana dan sangat fleksibel

Saya benar-benar tidak suka menulis banyak atau menulis banyak monkey codesuka:

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

ValueInjecter adalah sesuatu seperti mozilla dengan pluginsnya , Anda membuat ValueInjections dan menggunakannya

ada injeksi built-in untuk perataan, tidak rata, dan beberapa yang dimaksudkan untuk diwariskan

dan itu berfungsi lebih baik dalam jenis aspek cara , Anda tidak harus menentukan semua properti 1-ke-1, alih-alih Anda melakukan sesuatu seperti:

ambil semua properti int dari sumber yang namanya diakhiri dengan "Id", ubah nilainya dan tetapkan masing-masing ke properti di objek sumber dengan nama yang sama tanpa akhiran Id dan tipenya diwarisi dari Entity, hal-hal seperti itu

jadi satu perbedaan yang jelas, ValueInjecter digunakan bahkan dalam bentuk windows dengan perataan dan tidak rata, begitulah fleksibelnya

(pemetaan dari objek ke kontrol dan kembali)

Automapper, tidak dapat digunakan dalam bentuk windows, tidak ada cacat, tetapi memiliki hal-hal bagus seperti pemetaan koleksi, jadi jika Anda memerlukannya dengan ValueInjecter Anda hanya melakukan sesuatu seperti:

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

Anda juga dapat menggunakan ValueInjecter untuk memetakan dari anonim dan dinamis obyek

perbedaan:

  • automapper membuat konfigurasi untuk setiap kemungkinan pemetaan CreateMap ()

  • valueinjecter menyuntikkan dari objek apa pun ke objek apa pun (ada juga kasus ketika Anda menyuntikkan dari objek ke jenis nilai)

  • automapper telah meratakannya, dan hanya untuk tipe sederhana atau dari tipe yang sama, dan itu tidak rata

  • valueinjecter hanya jika Anda membutuhkannya Anda lakukan target.InjectFrom<FlatLoopValueInjection>(source); also <UnflatLoopValueInjection> dan jika Anda inginkan dari Foo.Bar.Name of type Stringke FooBarName of type Class1Anda mewarisi FlatLoopValueInjection dan menentukan ini

  • automapper memetakan properti dengan nama yang sama secara default dan untuk sisanya Anda harus menentukan satu per satu, dan melakukan hal-hal seperti Prop1.Ignore (), Prop2.Ignore () dll.

  • valueinjecter memiliki injeksi default .InjectFrom () yang melakukan properti dengan nama dan tipe yang sama; untuk segala sesuatu yang lain Anda membuat proyeksi nilai kustom Anda dengan logika / aturan pemetaan individual, lebih seperti aspek, misalnya dari semua properti Tipe Foo ke semua properti tipe Bar

Omu
sumber
5
Untuk dewa cinta tolong katakan padaku ValueInjector dapat mengambil grafik ViewModel dan peta ke / dari grafik yang dalam Entitas Bisnis dan memetakan segala sesuatu yang persis sama tanpa pekerjaan, dan bahwa saya hanya perlu menentukan cara menangani apa yang berbeda. Saya berharap AutoMapper akan menambahkan kemampuan ini tetapi tidak pernah terwujud dan saya belum punya waktu untuk menulis mapper otomatis saya sendiri.
Chris Marisic
3
@ Chris Marisic Anda dapat menggunakannya melakukannya, jika Anda maksud kloning dalam, saya melakukan satu injeksi sekali yang agak melakukan ini secara rekursif tetapi tidak bekerja untuk koleksi properti valueinjecter.codeplex.com/Thread/View.aspx?ThreadId=236126 , atau Anda dapat melakukan Flat ViewModel dan menggunakan perataan dan perataan, ini akan mudah
Omu
ViewModel dan Entitas Domain akan serupa tetapi berbeda, jadi bukan klon murni. 90% properti biasanya jenis dan nama yang tepat, ViewModels sering berakhir dengan SelectLists dan hal-hal yang terikat padanya yang ingin saya abaikan kembali ke domain. Keduanya sangat mungkin memiliki koleksi benda pada mereka.
Chris Marisic
27
<pedant>Terlihat keren, tapi mungkin itu ValueInjectOr? </pedant>
Craig Stuntz
1
tapi untuk beberapa alasan itu er :)
Omu
59

Karena saya belum pernah menggunakan alat lain, saya hanya dapat berbicara tentang AutoMapper. Saya memiliki beberapa tujuan untuk membangun AutoMapper:

  • Mendukung perataan untuk membodohi objek DTO
  • Mendukung skenario yang jelas di luar kotak (koleksi, enumerasi dll.)
  • Mampu memverifikasi pemetaan dalam suatu tes
  • Izinkan kasus tepi untuk menyelesaikan nilai dari tempat lain (tipe kustom-> pemetaan tipe, pemetaan anggota individu, dan beberapa kasus tepi benar-benar gila).

Jika Anda ingin melakukan hal-hal ini, AutoMapper bekerja dengan sangat baik untuk Anda. Hal-hal yang tidak dilakukan AutoMapper dengan baik adalah:

  • Mengisi objek yang ada
  • Tidak merata

Alasannya saya tidak pernah perlu melakukan hal-hal ini. Sebagian besar, entitas kami tidak memiliki setter, tidak mengekspos koleksi, dll. Jadi itu sebabnya tidak ada. Kami menggunakan AutoMapper untuk meratakan ke DTO dan memetakan dari model UI untuk memerintahkan pesan dan sejenisnya. Di situlah ia bekerja dengan sangat baik untuk kita.

Jimmy Bogard
sumber
1
@ Jim Bogard Apakah Anda melihat bahwa Mengisi objek yang ada akan membuatnya ke daftar fitur untuk AutoMapper?
Roman
Saya belum mencoba ValueInjecter, tetapi untuk apa yang kami butuhkan, automapper sangat kuat.
richb01
Saya pikir yang paling penting di sini adalah verifikasi. Ketika mengganti nama dan refactoring hal-hal ini sangat membantu.
Kugel
55

Saya mencoba keduanya dan lebih suka ValueInjecter karena sangat sederhana:

myObject.InjectFrom(otherObject);

Hanya itu yang perlu diketahui untuk sebagian besar kebutuhan injeksi saya. Tidak mungkin menjadi lebih sederhana dan elegan dari ini.

Adrian Grigore
sumber
1
this objectmetode penyuluhan di sana?
Chris Marisic
2
Bagaimana saya memisahkan kode saya dari ValueInjecter? Bagi saya sepertinya selalu memiliki ketergantungan pada ValueInjecter yaitu dalam proyek web saya, karena saya menggunakan ValueInjecter (metode ekstensi) pada objek yang diberikan LANGSUNG.
Rookian
1
@Rookian jujur ​​ini bukan masalah yang harus kamu pikirkan terlalu banyak. Anda bisa bergantung pada antarmuka seperti @Omu yang disebutkan jadi jika Anda pernah mengubah pemetaan Anda mungkin menyimpan beberapa pekerjaan (mungkin tidak banyak). Jenis dependensi ini terlalu sulit untuk diabstraksi kecuali Anda ingin masuk ke dalam AOP yang gagal yang sayangnya berkali-kali tidak dapat diurusi karena .NET tidak membantu memberikan dukungan AOP dengan benar. Sekarang Anda bisa AOP menghilangkan beberapa pemetaan, terutama jika Anda menggunakan MVC dan menulis Filter Tindakan yang menangani pemetaan ViewModel / DomainModel.
Chris Marisic
13
mengapa bungkus merupakan solusi terbaik? Satu-satunya hal yang perlu Anda lakukan jika ingin beralih mapper adalah menerapkan InjectFrom()metode ekstensi sendiri.
jgauffin
1
Saya telah mencoba keduanya dan saya lebih suka AutoMapper. Saya menggunakannya untuk sebagian kecil dari sistem saya di mana saya memetakan Entitas dengan Linq2Sql menghasilkan kelas. Pemetaan sederhana sebagai StockTotalQuantity -> stock_size_quantity atau UserId -> user_id bekerja dengan AutoMapper secara default. Itu tidak bekerja dengan ValeInjecter bahkan setelah menambahkan convetion. Berpegang pada AutoMapper untuk saat ini.
Artur Kędzior
27

Ini adalah pertanyaan yang telah saya teliti juga, dan untuk kasus penggunaan saya, sepertinya itu adalah pemberi nilai yang dijatuhkan. Ini tidak memerlukan setup sebelumnya untuk menggunakan (saya kira kinerja, saya kira, meskipun jika diimplementasikan dengan cerdas itu bisa membuat cache pemetaan untuk doa masa depan daripada mencerminkan setiap kali), jadi Anda tidak perlu menentukan terlebih dahulu pemetaan apa pun sebelum menggunakannya.

Namun yang paling penting, ini memungkinkan pemetaan terbalik. Sekarang saya mungkin kehilangan sesuatu di sini karena Jimmy menyebutkan bahwa dia melihat ada use case di mana diperlukan, jadi mungkin saya memiliki pola yang salah, tetapi use case saya adalah saya membuat objek ViewModel dari ORM saya. Saya kemudian menampilkan ini di halaman web saya. Setelah pengguna selesai, saya mendapatkan ViewModel kembali sebagai httppost, bagaimana cara ini dikonversi kembali ke kelas ORM asli? Saya ingin tahu polanya dengan automapper. Dengan ValueInjector itu sepele, dan itu bahkan tidak akan rata. mis. Membuat entitas baru

Model yang dibuat oleh entitas entitas (model pertama):

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

ViewModel (yang dapat saya hias dengan validator):

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

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

Menurut saya, tidak lebih sederhana dari itu?

(Jadi ini menimbulkan pertanyaan, apa yang salah dengan pola yang saya alami (dan sepertinya banyak yang melakukannya), yang tidak dilihat sebagai nilai bagi AutoMapper?)

Namun, jika pola ini seperti yang diuraikan, adalah salah satu yang ingin Anda gunakan, maka suara saya adalah pemberi nilai oleh mil negara.

DanH
sumber
1
mungkin Anda juga harus menanyakan hal ini dalam pertanyaan terpisah yang ditandai dengan asp.net-mvc dan best-practices, ViewModel ..., atm Saya tidak melihat masalah selama itu bekerja dengan baik untuk Anda, tapi saya yakin bahwa seseorang mungkin memiliki pendapat yang berbeda
Omu
Nah setelah belajar lebih banyak MVC. Sekarang saya bisa menjawab pertanyaan saya. Cara untuk memperbarui model asli ketika Anda mendapatkan kembali model tampilan yang dihuni, adalah dengan menggunakan fungsi UpdateModel () yang disediakan oleh mvc.
DanH
1
UpdateModel () digunakan untuk mengisi Model yang mewakili tampilan, dan sama dengan melakukan Aksi (model MyModelClasss)
Omu
Benar, tetapi jika Anda ingin memiliki model tampilan terpisah untuk misalnya model respositori, maka dapat digunakan untuk mengisi bahwa dengan asumsi pemetaan itu sepele (dan sering itu). Tentu saja jika ValueInjector yang lebih kompleks muncul dengan sendirinya.
DanH
1
Saya pikir argumen dapat dibuat bahwa Anda seharusnya tidak hanya mengatur properti Anda kembali pada model domain Anda - Anda harus menggunakan metode yang menambah makna padanya.
Mike Cole