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

标签 c# .net design-patterns

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

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

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

  • 关于我们应该根据 Foo 字段值选择哪个 Bar 后代的规则。例如,如果 foo.Type == "A"foo.Complex == truefoo 应转换为 BarC 对象。
  • 关于如何将 foo 字段转换为 BarXXX 字段的规则。例如,如果我们选择 BarA 作为目标类,那么 foo.Date 应该转换为 barA.DateA。但是如果我们选择 BarCfoo.Date 应该被转换为 barC.DateCbarC.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/

相关文章:

c# - BindingList with IList<T> DataSource,元素顺序

c# - Java 与 C# 机器代码做同样的事情

c# - .NET C# 中的 IdnMapping.GetAscii 方法未按预期工作

language-agnostic - 游戏对象库的代码与配置

c# - 如何将文件从 windows 复制到单声道的 mac?

c# - 引用类型的字段如何可以是非 volatile 的?

.net - WCF 客户端证书停止工作

.net - ThreadStatic 与 ThreadLocal<T> 性能 : speedups or alternatives?

c# - 数据访问层——模块化和可重用性

design-patterns - 动态访问对象方法