1

複雑なクラスのオブジェクトとFoo、次のような枝分かれした型階層があるとします。

class Bar {}
class BarA:Bar{}
class BarB:Bar{}
class BarC:BarA{}

タスクは、Foo オブジェクトを Bar の子孫の 1 つに変換することです。2 つのルール セットがあります。

  • フィールド値Barに従ってどの子孫を選択するかについてのルール。Fooたとえば、iffoo.Type == "A"foo.Complex == truethanはオブジェクトfooに変換する必要がありBarCます。
  • fooフィールドをフィールドに変換する方法に関する規則BarXXX。たとえば、BarAをターゲット クラスとして選択した場合、 をfoo.Dateに変換する必要がありますbarA.DateA。しかし、選択した場合はBarCfoo.Dateに変換する必要があり、 に変換する必要がbarC.DateCありbarC.DateAますDateTime.MinValue

車輪の再発明や、条件付きロジックの調子でスパゲッティ コードを書くことを避けたいだけです。ここでは AutoMapper と ValueInjecter は役に立たないと思います。エレガントなソリューションを探しています。アドバイスをお願いします。

4

1 に答える 1

1

高度なパターンを使用する必要はありません。タプルの単純なリストで{predicate, builder}十分に要件を満たすことができます。

次のように、 type のリストを作成しIList<Tuple<Predicate<Foo>,Func<Foo,Bar>>>、それに「チェッカー」と「メーカー」のペアを追加します。

private static readonly IList<Tuple<Predicate<Foo>,Func<Foo,Bar>>> CheckersAndMakers =
    new List<Tuple<Predicate<Foo>,Func<Foo,Bar>>>()
{
    new Tuple<Predicate<Foo>,Func<Foo,Bar>>(
        f => f.Type == "A" && f.Complex  // Checker
    ,   f => new BarC {DateC = foo.Date} // Maker
    )
,   new Tuple<Predicate<Foo>,Func<Foo,Bar>>(
        f => f.Type == "C" && !f.Complex  // Checker
    ,   f => new BarA {DateA = DateTime.MinValue} // Maker
    )
};

これで、ループでチェッカーを通過し、一致したときに対応するメーカーを使用できます。

Bar MakeFromFoo(Foo f) {
    foreach (var tuple in CheckersAndMakers) {
        if (tuple.Item1(f)) {
            return tuple.Item2(f);
        }
    }
    throw new ApplicationError("Unrecognized foo");
}
于 2012-09-18T15:26:10.593 に答える