1

假设我们有一些复杂类的对象Foo和一些分支类型层次结构,例如:

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

任务是将 Foo 对象转换为 Bar 后代之一。我们有两组规则:

  • Bar关于我们应该根据Foo字段值选择哪个后代的规则。例如, iffoo.Type == "A"foo.Complex == truethanfoo应该转换为BarCobject。
  • 关于如何将foo字段转换为BarXXX字段的规则。例如,如果我们选择BarA作为目标类,foo.Date则应该转换为barA.DateA. 但如果我们选择BarCfoo.Date应该转换为barC.DateC应该barC.DateADateTime.MinValue

我只是想避免重新发明轮子并使用条件逻辑编写意大利面条代码。我认为 AutoMapper 和 ValueInjecter 在这里无济于事。我正在寻找一些优雅的解决方案。请问有什么建议吗?

4

1 回答 1

1

There is no need to go for an advanced pattern: a simple list of tuples {predicate, builder} is sufficient to satisfy your requirements.

Create a list of type IList<Tuple<Predicate<Foo>,Func<Foo,Bar>>>, and add pairs of "checkers" and "makers" to it, as follows:

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

Now you can go through the checkers in a loop, and use its corresponding maker when you have a match:

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 回答