假设我们有一些复杂类 Foo
的对象和一些分支类型层次结构,例如:
class Bar {}
class BarA:Bar{}
class BarB:Bar{}
class BarC:BarA{}
任务是将 Foo 对象转换为 Bar 后代之一。我们有两套规则:
- 关于我们应该根据
Foo
字段值选择哪个Bar
后代的规则。例如,如果foo.Type == "A"
和foo.Complex == true
则foo
应转换为BarC
对象。 - 关于如何将
foo
字段转换为BarXXX
字段的规则。例如,如果我们选择BarA
作为目标类,那么foo.Date
应该转换为barA.DateA
。但是如果我们选择BarC
,foo.Date
应该被转换为barC.DateC
而barC.DateA
应该是DateTime.MinValue
。
我只是想避免重新发明轮子和编写带有条件逻辑色调的意大利面条代码。我认为 AutoMapper 和 ValueInjecter 在这里无济于事。 我正在寻找一些优雅的解决方案。有什么建议吗?
最佳答案
不需要高级模式:一个简单的元组列表 {predicate, builder}
足以满足您的要求。
创建类型为 IList<Tuple<Predicate<Foo>,Func<Foo,Bar>>>
的列表, 并向其中添加成对的 "checkers"和 "makers",如下所示:
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");
}
关于c# - 具有复杂逻辑的对象到对象转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12479773/