AutoMapper vs ValueInjecter [終了]


209

StackOverflowでAutoMapperを探すたびにValueInjecterについて何かを読んでいます。

誰かが長所と短所(パフォーマンス、機能、APIの使用法、拡張性、テスト)を教えてくれませんか?


2
私がよく言及したもう1つはEmitMapperです。
adrianbanks 2011年

1
接着剤はどうですか?glue.codeplex.comも素晴らしいプロジェクトのように見えますが、まだ試していません。でも来月中にします。私はまた、EmitMapperと呼ばれるプロジェクトを見てきましたemitmapper.codeplex.com
トリグヴェ

これら2つのツールについて話す記事を参照してください-devproconnections.com/development/…–
George Birbilis

回答:


170

ValueInjecterの作成者として、シンプルで非常に柔軟なものが欲しかったので、それを行ったと言えるでしょう。

私は本当にたくさん書いたり、たくさん書いたりするのが好きではありませんmonkey code

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

ValueInjecterはプラグインを備えたmozillaのようなもので ValueInjectionsを作成して使用します

平坦化、非平坦化のための組み込みの注入があり、一部は継承を目的としています

アスペクトタイプの方法でより効果的に機能します。すべてのプロパティを1対1で指定する必要はなく、代わりに次のようにします。

名前が「Id」で終わるすべてのintプロパティをソースから取得し、値を変換して、Idサフィックスのない同じ名前のソースオブジェクトのプロパティにそれぞれ設定します。そのタイプはEntityから継承されます。

明らかな違いの1つは、ValueInjecterがフラット化と非フラット化のあるWindowsフォームでも使用されることです。

(オブジェクトからフォームコントロールへのマッピングとその逆)

オートマッパー、Windowsフォームでは使用できません、展開解除はありませんが、コレクションマッピングのような優れた機能があるため、ValueInjecterで必要な場合は、次のようにします。

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

あなたもからマップするためにValueInjecterを使用することができ、匿名動的なオブジェクト

違い:

  • マッピングの可能性ごとにautomapper create構成CreateMap()

  • valueinjecterは、任意のオブジェクトから任意のオブジェクトに注入します(オブジェクトからvaluetypeに注入する場合もあります)

  • オートマッパーはフラット化を組み込んでおり、シンプルなタイプまたは同じタイプのみを対象としており、フラット化を解除しません

  • valueinjecterあなたはあなたがそれを必要とする場合にのみtarget.InjectFrom<FlatLoopValueInjection>(source); also <UnflatLoopValueInjection> 、あなたがからしたい場合Foo.Bar.Name of type StringFooBarName of type Class1あなたがFlatLoopValueInjectionを継承し、これを指定します

  • automapperはデフォルトで同じ名前のプロパティをマップします。それ以外の場合は、1つずつ指定し、Prop1.Ignore()、Prop2.Ignore()などを実行する必要があります。

  • valueinjecterには、同じ名前とタイプのプロパティを実行するデフォルトの注入.InjectFrom()があります。それ以外の場合は、たとえば、タイプFooのすべての小道具からタイプバーのすべての小道具まで、アスペクトに似た個別のマッピングロジック/ルールを使用してカスタム値インジェクションを作成します


5
ValueInjectorはディープグラフのViewModelを取得し、ディープグラフのビジネスエンティティとの間でマッピングを行って、まったく同じことを何も行わずにすべてをマッピングできること、そして何が違うのかを処理する方法を指定するだけでよいことを教えてください。私はAutoMapperがこの機能を追加することを望んでいましたが、これが実現したことはなく、自分の自動マッパーを作成する時間もありませんでした。
Chris Marisic、2011年

3
@Chris Marisicあなたはそれを使うことができます、あなたがディープクローニングを意味する場合、私は一度再帰的にこれを行うと一度インジェクションを行いましたが、コレクションのプロパティでは機能しませんvalueinjecter.codeplex.com/Thread/View.aspx?ThreadId=236126、またはFlat ViewModelを実行してフラット化と非フラット化を使用できます。これは簡単です
Omu

ViewModelとDomain Entitiesは似ていますが異なるため、純粋なクローンではありません。プロパティの90%は通常、正確なタイプと名前です。ViewModelは、ドメインに戻ることを無視したいSelectListやそれらにバインドされたもので終わることがよくあります。ただし、どちらにもオブジェクトのコレクションがある可能性が非常に高いです。
Chris Marisic、2011年

27
<pedant>かっこいいですが、おそらくValueInjectOrでしょうか?</pedant>
Craig Stuntz、2011年

1
しかし、何らかの理由でer :)
Omu

59

他のツールを使用したことがないので、AutoMapperについてのみ説明します。AutoMapperの構築には、いくつかの目標がありました。

  • ダムDTOオブジェクトへのフラット化をサポート
  • すぐに使える明白なシナリオ(コレクション、列挙など)をサポートする
  • テストでマッピングを簡単に検証できる
  • 他の場所からの値を解決するためのエッジケースを可能にします(カスタムタイプ->タイプマッピング、個々のメンバーマッピング、およびいくつかの本当にクレイジーエッジケース)。

これらのことを実行したい場合、AutoMapperは非常にうまく機能します。AutoMapperがうまくいかない点は次のとおりです。

  • 既存のオブジェクトを埋める
  • 平坦化していない

その理由は、私がこれらのことをする必要がなかったからです。ほとんどの場合、エンティティにはセッターやコレクションが公開されていないなどの理由で、そこにはありません。AutoMapperを使用してDTOにフラット化し、UIモデルからコマンドメッセージなどにマップします。それは私たちにとって本当にうまくいくところです。


1
@Jimmy Bogard既存のオブジェクトを塗りつぶすとAutoMapperの機能リストに入ることがわかりますか?
ローマ、

私はValueInjecterを試していませんが、私たちが必要としているものに対して、オートマッパーは非常に強力です。
richb01

ここで最も重要なことは検証可能性だと思います。名前の変更やリファクタリングを行う場合、これは非常に役立ちます。
Kugel 2014

55

私は両方を試してみましたが、とてもシンプルなのでValueInjecterを好みます:

myObject.InjectFrom(otherObject);

私の注射のニーズの大部分について知っておくべきことは、これですべてです。これほどシンプルでエレガントになることはありません。


1
this objectそこに拡張方法?
Chris Marisic、2011年

2
コードをValueInjecterから分離するにはどうすればよいですか?私にとっては、常に指定されたオブジェクトでValueInjecter(拡張メソッド)を直接使用するため、ValueInjecter(つまり、私のWebプロジェクト)に依存しているようです。
Rookian、2011年

1
@Rookian正直に言って、これはあなたがあまりに考えるべき問題ではありません。@Omuのようにインターフェイスに依存することができるので、マッパーを変更した場合、作業量を節約できる可能性があります(おそらくそれほど多くありません)。.NETはAOPサポートを正しく提供できないため、残念ながら何度も元に戻すことができない本格的なAOPを使いたくない限り、このタイプの依存関係を抽象化するのは非常に困難です。これで、特にMVCを使用して、ViewModel / DomainModelマッピングを処理するアクションフィルターを作成する場合に、マッピングの一部をAOPで取り除くことができます。
Chris Marisic、2011年

13
ラッパーが最適なソリューションである理由 マッパーを切り替える場合は、InjectFrom()拡張メソッドを自分で実装する必要があります。
jgauffin 2011年

1
私も両方を試しましたが、AutoMapperを好みます。エンティティをLinq2Sqlで生成されたクラスにマップするシステムのごく一部に使用しました。StockTotalQuantity-> stock_size_quantityまたはUserId-> user_idとしての単純なマッピングは、デフォルトでAutoMapperで機能しました。変換を追加した後でも、ValeInjecterでは機能しませんでした。現時点ではAutoMapperを使用しています。
ArturKędzior2012年

27

これは私も調査してきた質問であり、私のユースケースでは、バリューインジェクターの手がかりのようです。使用する前にセットアップする必要はありません(パフォーマンスに影響する可能性がありますが、スマートに実装すると、毎回反映するのではなく、将来の呼び出しのためにマッピングをキャッシュすることができます)。したがって、使用する前にマッピングを事前定義する必要はありません。

ただし、最も重要なのは、逆マッピングが可能なことです。ここで、ジミーが必要なユースケースがないと述べているので、ここで何か不足している可能性があります。パターンが間違っている可能性がありますが、私のユースケースでは、ORMからViewModelオブジェクトを作成しています。次に、これを自分のWebページに表示します。ユーザーが完了したら、ViewModelをhttppostとして戻す場合、これを元のORMクラスに変換するにはどうすればよいですか?自動マッパーでパターンを知りたいです。ValueInjectorを使用すると、それは取るに足らないことであり、平坦化さえされません。例:新しいエンティティの作成

entityframeworkによって作成されたモデル(最初のモデル):

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(バリデータで飾ることができます):

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

私の考えでは、それよりもはるかに単純ではありませんか?

(つまり、これは私にこれに遭遇するパターンの何が問題であるか(そして他の多くの人がそうしているようです)、問題を引き起こします、それはAutoMapperにとって価値があるとは考えられていません?)

ただし、このパターンが説明どおりであり、使用したいパターンである場合、私の投票はカントリーマイル単位のバリューインジェクターです。


1
おそらく、asp.net-mvcとbest-practices、ViewModel ...でタグ付けされた別の質問でもこれを質問する必要があります。誰かが別の意見を持っているかもしれません
Omu

より多くのMVCを学びました。これで私の質問に答えることができます。設定されたビューモデルを取得したときに元のモデルを更新する方法は、mvcが提供するUpdateModel()関数を使用することです。
DanH

1
UpdateModelは()アクション(MyModelClasssモデル)やってと同じようにビューを表すモデルを移植するために使用されており、かつ
OMU

正しいですが、たとえばリポジトリモデルなどの別のビューモデルが必要な場合は、マッピングを使用すると仮定して簡単に作成できます(多くの場合そうです)。もちろん、もっと複雑なValueInjectorが登場した場合。
DanH

1
ドメインモデルにプロパティを単に設定するだけでなく、意味を追加するメソッドを使用する必要があるという議論もあると思います。
マイクコール
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.