我在克隆对象时遇到了一些问题。它是用于建模应用程序的工具包,工具箱包含类实例作为原型。但是我很难克隆这些:)
以下代码显示了问题:
public abstract class Shape {
protected List<UIElement> elements;
private Canvas canvas;
...
public Canvas getCanvas() { ... };
}
public class MovableShape : Shape {
protected ... propertyA;
private ... propertyXY;
...
}
public abstract class AbstractLayout : MovableShape, ... {
...
}
public class SomeLayoutClass : AbstractLayout, ... {
...
}
public class AContainingClass {
SomeLayoutClass Layout { get; set; }
...
}
当我将AContainingClass
的对象插入到我的项目工作表中时,应该克隆它。到目前为止,我尝试了手动克隆(由于基类中的private
字段而失败)和二进制序列化(BinaryFormatter
和MemoryStreams
)。
第一种方法缺少调用base.clone()
方法的方法(或者我错了?),后者不起作用,因为UIElement
不是[Serializable]
。
注意:它必须是深拷贝!
有什么想法吗?谢谢!
<小时/> UPDATE
只是为了澄清我的手动克隆方法:
如果每个类都有自己的Clone
方法,那么如何调用基类的Clone
方法?
public class Shape { // not abstract any more
...
public Shape Clone() {
Shape clone = new Shape() { PropertyA = this.PropertyA, ... };
...do some XamlWriter things to clone UIElements...
return clone;
}
}
public class MovableShape : Shape {
...
public MovableShape Clone() {
// how to call base.Clone???
// this would be required because I have no access to the private fields!
}
}
答案 0 :(得分:6)
这里有它的功能:
public T XamlClone<T>(T source)
{
string savedObject = System.Windows.Markup.XamlWriter.Save(source);
// Load the XamlObject
StringReader stringReader = new StringReader(savedObject);
System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(stringReader);
T target = (T)System.Windows.Markup.XamlReader.Load(xmlReader);
return target;
}
答案 1 :(得分:3)
如果您尝试克隆UIElements,请使用XamlWriter保存为字符串,但没有任何克隆方法是万无一失的。然后使用XamlReader加载副本。你仍然可能遇到问题。像处理程序没有被复制,x:名称被复制等等。但对于像Grid或Brush这样的简单元素,它的效果很好。
编辑1:但是,没有通用的方法可以克隆任何内容:
1)如果正确编写了克隆函数,它将为您调用基本克隆,并复制基类类。如果没有正确写入调用基础克隆将无济于事,尽管您可以调用私有方法this way。
2)如果必须,你可以使用Reflection来复制几乎任何东西,甚至点击处理程序,从旧对象到新对象。
3)XamlWriter和XamlReader将复制和实例化对象的heirarchies,只是减去某些属性。
编辑2:这是我在类层次结构中使用的常见克隆设计模式。假设基类形状,派生类圈:
protected Circle(Circle t)
{
CopyFrom(t);
}
public override object Clone()
{
return new Circle(this);
}
protected void CopyFrom(Circle t)
{
// Ensure we have something to copy which is also not a self-reference
if (t == null || object.ReferenceEquals(t, this))
return;
// Base
base.CopyFrom((Shape)t);
// Derived
Diameter = t.Diameter;
}
答案 2 :(得分:0)
我自己没有尝试过,但XamlWriter看起来很有希望。