2011-07-20 6 views
2

オブジェクト階層のクローニングにはいくつかの問題があります。これはモデリングアプリケーション用のツールキットで、ツールボックスにはクラスインスタンスがプロトタイプとして含まれています。しかし、私はこれら:)WPFコントロールとオブジェクト階層のクローニング

次のコードをクローニング苦労が問題を示していたよ:私は私のプロジェクトのワークシートへAContainingClassのオブジェクトを挿入すると

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

、それをクローン化する必要があります。これまでは手動クローニング(基本クラスのprivateフィールドのため失敗しました)とバイナリシリアル化(BinaryFormatterMemoryStreams)を試しました。

[Serializable]ではないため、最初の方法ではbase.clone()メソッドを呼び出す方法がありません(または間違っていますか?)、後者は機能しません。

注:ディープコピーである必要があります。

アイデア?ありがとう!


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

、手動のクローン作成は、まったく動作しないことができる、またはそれだけで扱いにくいましたか?民間の状態は公的な状態に対応していないのですか?扱いにくい場合は、リフレクションベースのコード生成を使用することをお勧めします。それ以外の場合、これらの欠点を修正するためにコードを複製することはオプションですか?ライブラリはオープンソースですか?もしそうなら、パッチを提出してオブジェクトをクローン可能にすることができます。 –

+0

@Merlyn Morgan-Graham:手動クローニング – Matten

答えて

3

あなたはのUIElementのクローンを作成しようとしている場合は、クローニングのない方法は誰にでもありませんが、文字列に保存するためにXamlWriterを使用しています。次に、XamlReaderを使用してコピーをロードします。あなたはまだ問題に遭遇する可能性があります。ハンドラーのようなものはコピーされません、x:名前は複製されます。しかし、グリッドやブラシのような単純な要素の場合、それは素晴らしいです。

編集1:しかし、何のクローンを作成する一般的な方法はありません。

1)クローン機能が正しく書かれている場合、それはあなたのための基本クローンを呼び出し、基本クラスのものをコピーします、あまりにも。それが正しく書かれていない場合、プライベートメソッドthis wayを呼び出すことはできますが、基本クローンを呼び出すことはあまり役に立ちません。

2)あなたがする必要がある場合は、Reflectionを使用して、古いオブジェクトから新しいオブジェクトにほとんどすべてのものをコピーしたり、ハンドラをクリックしたりすることもできます。

3)XamlWriterとXamlReaderは、特定のプロパティを除いたオブジェクトの階層をコピーしてインスタンス化します。

編集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; 
} 
+0

のコード例を追加しましたが、残りのクローンを作成する方法はありますか? (私の更新を参照してください) – Matten

+0

私は私の答えを更新しました。クローンを作成する一般的な方法はありませんが、私はより多くの情報を与えました。ありがとう。 –

+0

ありがとう。しかし、ポイント1)私に問題を与えている、私のクローン関数は、希望どおりに動作していない:)私は 'base.clone()'を正しく呼び出す方法がわからない。 – Matten

1

自分で試したことはありませんが、XamlWriterは有望そうです。

+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; 
    } 
関連する問題