具有复杂逻辑的对象到对象的转换

时间:2012-09-18 15:06:33

标签: c# .net design-patterns

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

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

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

  • 我们应根据Bar字段值选择Foo后代的规则。例如,如果foo.Type == "A"foo.Complex == true而不是foo应转换为BarC对象。
  • 有关如何将foo字段转换为BarXXX字段的规则。例如,如果我们选择BarA作为目标类,则应将foo.Date转换为barA.DateA。但是,如果我们选择BarC,则foo.Date应转换为barC.DateC,而barC.DateA应为DateTime.MinValue

我只是想避免重新发明轮子并用条件逻辑的音调编写spagetti代码。我认为AutoMapper和ValueInjecter在这里没有帮助。 我正在寻找一些优雅的解决方案。有什么建议吗?

1 个答案:

答案 0 :(得分:1)

无需使用高级模式:简单的元组列表{predicate, builder}足以满足您的要求。

创建一个类型为IList<Tuple<Predicate<Foo>,Func<Foo,Bar>>>的列表,并添加一对“checkers”和“maker”,如下所示:

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