假设我们有一些复杂类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在这里没有帮助。 我正在寻找一些优雅的解决方案。有什么建议吗?
答案 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");
}