前面冗长的软件架构问题
清晰度编辑:我正在尝试将包含
NodeA
, NodeB
, ...等类型的对象图转换为包含*My*NodeA
, ... 等类型的对象图,*My*NodeB
反之亦然。类型中的属性NodeX
对应于类型中的相似属性MyNodeX
,但在许多情况下,它不仅仅是一个简单的赋值。
如果我有两个类似的类结构:
// pure model, i.e. minimal information that is convenient for storage
abstract class Node
{
public int BaseProperty { get; set; }
public NodeCollection Children { get; private set; } // : Collection<Node>
}
class NodeA /* NodeB, NodeC ... */ : Node
{
public int DerivedAProperty { get; set; }
}
和
// objects that are convenient for being used by the application
abstract class MyNode
{
public int MyBaseProperty { get; set; }
public MyNodeCollection Children { get; private set; } // : Collection<MyNode>
}
class MyNodeA /* MyNodeB, MyNodeC ... */ : MyNode
{
public int MyDerivedAProperty { get; set; }
}
,并且我需要将NodeX
类型的对象图转换为其中一种MyNodeX
类型,反之亦然,根本不更改任何NodeX
类,我发现自己经常使用这种模式:
NodeX -> MyNodeX
// USAGE / external code
Node node = ...
MyNode myNode = MyNode.Load(node, ARGS); // static factory
abstract class MyNode
{
...
// factory
public static MyNode Load(Node node, ARGS)
{
var type = node.GetType();
MyNode myNode;
// no 'is' usage because NodeB could be derived from NodeC etc.
if (type == typeof(NodeA))
myNode = new MyNodeA(ARGS); // arbitrary ctor
else if (...)
...
myNode.Load(Node);
return myNode
}
public virtual void Load(Node node)
{
this.MyBaseProperty = node.BaseProperty;
foreach (var child in node.Children)
this.Children.Add(MyNode.Load(child, this.ARGS));
}
}
class MyNodeA : MyNode
{
...
public override void Load(Node node)
{
var m = (NodeA)node; // provoke InvalidCastException if coding error
base.Load(node);
this.MyDerivedAProperty = m.DerivedAProperty;
}
}
MyNodeX -> 节点X
// USAGE / external code
MyNode myNode = ...
Node node = myNode.Commit();
abstract class MyNode
{
...
// 'kind of' factory
public abstract Node Commit();
public virtual Commit(Node node)
{
node.BaseProperty = this.MyBaseProperty;
foreach (var child in this.Children)
node.Children.Add(child.Commit());
}
}
class MyNodeA : MyNode
{
...
public override Node Commit()
{
var m = new NodeA(); // "factory" method for each type
this.Commit(m);
return m;
}
public override void Commit(Node node)
{
var m = (NodeA)node; // provoke InvalidCastException if coding error
base.Commit(node);
m.DerivedAProperty = this.MyDerivedAProperty;
}
}
我已经多次成功地使用了这种方法,而且我一般都喜欢它,因为必须添加到类中的方法是直截了当的,外部代码也是如此。base.Load(node)
此外,它通过调用/来避免代码重复base.Commit(node)
。但是,我真的不喜欢静态Load
工厂方法中的 if/else 阶梯。
对于Node -> MyNode ( ) 情况,我希望在每种类型中都有一个工厂方法Load
,类似于在MyNode -> Node ( Commit
) 情况下的情况。但是static
,virtual
显然有点问题。我也宁愿不做我现在必须做的两个演员。
以某种方式实现这样的事情是可能的吗?