【问题标题】:Cast/Convert tree structure to different type将树结构转换/转换为不同的类型
【发布时间】:2012-08-21 20:24:46
【问题描述】:

如果我有课:

class NodeA
{
      public string Name{get;set;}
      public List<NodeA> Children {get;set;}
      // etc some other properties
}

和其他一些类:

class NodeB
{
      public string Name;
      public IEnumerable<NodeB> Children;
      // etc some other fields;
}

如果我需要将 NodeB 对象转换为 NodeA 类型,最好的方法是什么?创建一个包装类?如果我必须创建一个包装类,我该如何创建它以便所有 wpf 控件仍然能够成功绑定到属性?

  • 为什么我需要创建这样的演员表:

    在程序中使用了一种旧算法,该算法在已编译的程序中返回符号列表 (IMemorySymbol)。我们已经工作并创建了一个新算法,并且字段和属性有些不同(ISymbolElem)。为了在 wpf 应用程序的视图中显示属性,我们需要执行临时转换。

【问题讨论】:

  • 好吧,你不能“转换”它,因为它们没有隐式转换。你可以想象“转换”它......不知何故。
  • 是的,所以我基本上必须遍历整个树并以某种方式转换它?
  • 这基本上就是 Automapper 开箱即用的功能。它使用反射来遍历所有属性,并复制数据。它的作用 - 它为您提供了一种很好且舒适的方式来描述如何映射道具。所以 5 页的 ForEach 循环更具可读性
  • 好吧,我上面的评论主要是一个术语问题。 “铸造”是将一个对象视为不同的类;这在这里行不通。 “转换”是创建一个不同类的新对象,但在逻辑上表示相同的值或事物。看看你有什么,我猜你也不能只转换一个节点;您需要转换整个树。

标签: c# data-structures casting tree


【解决方案1】:

几种方法...

复制构造函数

有一个 NodeA 和 NodeB 包含一个相反的构造函数:

class NodeA 
{ 
    public string Name{get;set;} 
    public List<NodeA> Children {get;set;} 

    // COPY CTOR
    public NodeA(NodeB copy)
    {
        this.Name = copy.Name;
        this.Children = new List<NodeA>(copy.Children.Select(b => new NodeA(b));
        //copy other props
    }
} 

显式或隐式运算符

显式你会像NodeA a = (NodeA)b;一样投射,而隐式你可以跳过括号。

public static explicit operator NodeA(NodeB b)
{
    //if copy ctor is defined you can call one from the other, else
    NodeA a = new NodeA();
    a.Name = b.Name;
    a.Children = new List<NodeA>();

    foreach (NodeB child in b.Children)
    {
        a.Children.Add((NodeA)child);
    }
}

【讨论】:

  • 关于隐式/显式转换运算符的说明。如果这两种类型相关,或者这种转换有意义(与 Tomatoes 和 TimeSpan 之间的转换相比),您真的应该只使用这种转换。 OP 的类型看起来相关,所以这是合适的。
【解决方案2】:

如果你不关心将NodeA的实现耦合到NodeB,那么添加一个复制构造函数如下:

class NodeA
{
    public NodeA() { }
    public NodeA(NodeB node)
    {
        Name = node.Name;
        Children = node.Children.Select(n => new NodeA(n)).ToList();
    }

    public string Name{get;set;}
    public List<NodeA> Children {get;set;}
    // etc some other properties
}

如果耦合是一个问题,那么您可以创建一个 Convert 样式的类来为您进行转换。请注意,Automapper 框架通过对源类型和目标类型使用反射为您生成这些类型的转换。

【讨论】:

    【解决方案3】:

    从一个通用接口继承怎么样?

    interface INode {
      public string Name{get;set;}
      public IEnumerable<INode> Children {get;set;}
    }
    
    class NodeA : INode {
      public string Name{get;set;}
      public List<NodeA> Children {get;set;}
      // etc some other properties
    }
    
    class NodeB : INode {
      public string Name;
      public IEnumerable<NodeB> Children;
      // etc some other fields;
    }
    
    void myMethod() {
      INode nodeB = new NodeB();
      INode nodeA = nodeB;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-08-07
      • 2011-06-10
      • 1970-01-01
      • 1970-01-01
      • 2011-05-03
      • 1970-01-01
      • 2017-10-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多