web-dev-qa-db-ja.com

AutoMapperとValueInjecter

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

誰かがそれらの間の長所と短所(パフォーマンス、機能、APIの使用、拡張性、テスト)を教えてもらえますか?

209
Rookian

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フォームでも使用されているため、柔軟性があります

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

Automapperは、Windowsフォームでは使用できず、展開されませんが、コレクションマッピングなどの優れた機能を備えているため、ValueInjecterで必要な場合は次のようにします。

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

valueInjecterを使用して、anonymousおよびdynamicオブジェクトからマッピングすることもできます

違い:

  • automapperは、マッピングの可能性ごとに構成を作成しますCreateMap()

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

  • オートマッパーは、単純化された型または同じ型からのみの平坦化を構築し、非平坦化は行いません

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

  • オートマッパーはデフォルトで同じ名前のプロパティをマップし、残りは1つずつ指定する必要があり、Prop1.Ignore()、Prop2.Ignore()などの処理を行います。

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

170
Omu

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

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

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

  • 既存のオブジェクトを埋める
  • 非平坦化

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

59
Jimmy Bogard

私は両方を試してみましたが、ValueInjecterはとてもシンプルだからです。

myObject.InjectFrom(otherObject);

私の注射のニーズの大部分について知っていることはそれだけです。これよりもシンプルでエレガントになることはおそらくないでしょう。

55
Adrian Grigore

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

ただし、最も重要なことは、逆マッピングを許可することです。ジミーが必要なユースケースを見ないと言及しているため、ここで何かを見逃している可能性があります。したがって、パターンが間違っている可能性がありますが、私のユースケースは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にとって価値がないと思われるという質問を請います)

ただし、このパターンが説明されているように使用したい場合、私の投票はカントリーマイルごとのバリューインジェクターです。

27
DanH