0

オーケー、シリアル化について SO で以前にいくつか質問したことがありますが、まだ立ち往生しているので、誰かが私の鼻を正しい方向に向けることができることを期待して、副次的な問題ではなく、ケース全体を吐き出します。 :)

私のアプリケーションは Apple の「Quartz Composer」に似ています。つまり、接続されたノードのツリーのような構造を持っています。

ノードは INode インターフェースによって定義されます。実際のノード タイプ/クラスは、MEF を使用して DLL からインポートされるため、ノード タイプはコンパイル時に認識されません。

ノードは接続されているため、双方向リンクが発生する可能性があります。

「構成」(ノードのツリー全体) を、できれば XML のように人間が判読できるファイルに保存したいと考えています。独自の形式で保存するのは本当に避けたいです。

したがって、シリアル化する必要があるのは次のとおりです。

  • オブジェクトのツリー。そのクラスは実行時にインポートできます (したがって、事前に認識されません)。双方向リンクを含めることができます。

  • さらに、使用されているノード クラスのバージョン情報を保存したいので、現在のアプリケーションで使用されている dll / ノード クラスよりも古いバージョンのノード クラスを使用して「コンポジション」が保存されているかどうかを確認できます。

以前、私は DataContractSerializer を指摘されました。これは、ツリーを格納し、双方向リンクを完全にサポートするための気の利いたツールのようです。

しかし、ツリー (Interface IComposition) をシリアル化する場合、不明な型について不平を言い始めます。ツリーのシリアル化中に発生する可能性のある特定の型をそれぞれ指定する必要があります...

また、特定のノード クラスに使用されたアセンブリ バージョンを指定する方法もありません。

どういうわけか、最初にツリー全体を列挙してどのノードクラスが使用されているかを調べ、これらを既知の型のリストに追加してからシリアル化するのは正しくないと感じています。

それでも、使用するクラスのバージョン情報を指定するセクションを output-data に追加する方法を見つける必要があります。

この問題を抱えているのは私だけかもしれませんが、他の誰かがこの問題に遭遇して克服したことを本当に願っています-できればエレガントなソリューションを使用してください;)標準の.NETシリアライザーで処理できるものではないと想像できますが、たぶん、サードパーティ(無料、オープンソースでも?)の実装がありますか?

4

1 に答える 1

0

BinaryFormatterまたはSoapFormatterを使用してこれを実現できます。これらのフォーマッタは、任意のオブジェクト グラフで動作し、遭遇したすべての[Serializable]オブジェクトを処理し (オブジェクトの型がマークされている限り)、循環参照を正しく保持します。オブジェクトがどのようにシリアライズされるかを知りたい場合は、XML を出力する SoapFormatter を使用してください。

オンデマンドで読み込むことができるアセンブリは、GAC にある必要があります。そうしないと、ランタイムがそれらを見つけられないことに注意してください。

バージョン管理に対処するには、次のようにします。

[Serializable]
public class SomeVersionedClass : IDeserializationCallback
{
    private const int CURRENT_VERSION = 10;

    private int version = CURRENT_VERSION;

    void IDeserializationCallback.OnDeserialization(object sender)
    {
        if (version != CURRENT_VERSION)
            throw new ApplicationException(
                "Mismatch between serialized data version " + version +
                " and required version " + CURRENT_VERSION + ".");
    }
}

例外をスローする代わりに、以前のバージョンのレイアウトから新しいバージョンにデータを移行することを検討する場合があることに注意してください。また、シリアライズされたフィールドをクラスから削除すると、将来のデシリアライズが完全に妨げられることに注意してください。そのため、使用されなくなったフィールドからの移行を許可する場合は、以前のバージョンが適切にデシリアライズできるように、そのフィールドをそのままにしておく必要があります (もちろん、データを取得して移行することもできます)。

于 2010-12-27T21:26:35.740 に答える