将树形结构转换为不同类型的Cast/Convert

4
如果我有这个类:
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控件仍然能够成功地绑定到属性?
创建一个包装类可能是最好的方法。您可以通过在包装类中定义与NodeB相同的属性和字段来实现此目的,并将其用作NodeA对象的代理。这样,您就可以使用新算法返回的ISymbolElem对象填充NodeB属性,并在WPF应用程序中正常显示。
需要创建这种转换的原因是:旧算法在编译的程序中返回符号列表(IMemorySymbol)。我们已经开发了一种新算法,字段和属性有所不同(ISymbolElem)。我们需要执行临时转换,以便在wpf应用程序的视图中显示属性。

3
由于没有隐式转换,所以你无法“强制转换”它。你可以想办法进行“转换”……一些方法。 - Servy
是的,我基本上必须遍历整个树,然后以某种方式进行转换? - Tono Nam
1
这基本上就是 Automapper 开箱即用的功能。它使用反射来遍历所有属性并复制数据。它所做的是为您提供一种描述如何映射属性的简便方式。因此,相比于五页的 ForEach 循环,它更易读。 - Marty
好的,我上面的评论主要是一个术语问题。“强制转换”是将一个对象视为不同的类;这在这里行不通。“转换”是创建一个新对象,它属于不同的类,但在逻辑上表示相同的值或事物。从你所拥有的东西来看,我的猜测也是你不能只转换一个节点;你需要转换整个树。 - Servy
3个回答

5

以下是一些方法...

拷贝构造函数

有一个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);
    }
}

1
关于隐式/显式转换运算符的说明。只有在两种类型相关或这样的转换有意义时(例如将番茄和时间间隔进行转换),您才应该使用此类转换。OP的类型看起来是相关的,因此这是适当的。 - Steve Guidi

1
如果您不关心将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框架通过对源类型和目标类型进行反射生成这些类型的转换。

1

从一个公共接口继承怎么样?

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接