2009-05-07 8 views
12

いくつかのクラスとデータ構造をファイルに保存する必要があります。私の最初の反応は、XMLまたはバイナリのシリアライゼーションを使用することでしたが、これは悪夢に変わっています。私は、プライベートセッター、無パラメータコンストラクター、シリアル化属性、辞書など、シリアル化するつもりはないクラスのセットを持っています。私はこれらのクラスを変更できないことを考慮して、どうすればよいですか?この問題を回避する方法はありますか?シリアル化されないように設計されたクラスをシリアル化する方法は?

私はプロパティ、コレクションなどを書くためのすべてのコードを記述する必要がありますか?

私が連載するのDTOを生成するコード生成ツール(mygeneration、T4、何でも)を使用することになり
+0

良い質問、パフォーマンスの要件と問題の規模を手近に詳しく説明できますか? –

+0

この時点では、私には本当に必要条件はありません。私は最もエレガントなソリューションを探しています。 – Martin

+1

あなたは本当に間違った解決策である可能性が高いソリューションを選択しても、ゼロ要件の問題に対するソリューションを設計することはできません。 –

答えて

9

JavaScriptSerializerを使用します。これはSystem.Web.Script.Serialization名前空間にあり、System.Web.Extensions.dllアセンブリの3.5フレームワークに実装されています。

このクラスでは、[Serializable]としてマークされているかどうかに関わらず、POCOをシリアル化できます。あなたのプログラムは、JSONのシリアル化を使用するためのWebアプリケーションである必要はありません。ここに例があります:

public class Unserializable 
{ 
    public int Age { get; set; } 
    public int ID { get; set; } 
    public string Name { get; set; } 
} 

public class Program 
{ 
    static void Main() 
    { 
    var u = new Unserializable 
      { 
       Age = 40, 
       ID = 2, 
       Name = "Betty" 
      }; 
    var jser = new JavaScriptSerializer(); 
    var jsonText = jser.Serialize(u); 
    // next line outputs {"Age":40,"ID":2,"Name":"Betty"} 
    Console.WriteLine(jsonText); 
    } 
} 
+0

+1私はそれを知らなかった。これはフィールドも扱いますか? –

+0

はい、フィールドも処理されます。これを試してみてください: public class Unserializable { public int Age; public int ID {get;セット; } public string Name {get;セット; } パブリックUnserializable(int年齢、int id、文字列名){ 年齢=年; ID = id; 名前=名前; } } var u =新しいUnserializable(40,2、 "Donna"); var jser = new JavaScriptSerializer(); var jsonText = jser.Serialize(u); Console.WriteLine( "{" {1}にJavaScriptSerializerを使用して{0}をシリアル化しました: "、 u.GetType()。名前、jsonText); パブリックフィールドを含むオブジェクトのJSONテキストを '{"Age":40、 "ID":2、 "Name": "Donna"}'として出力します。 –

0

...

+0

コードの問題を解決するには、クラスを変更する場合にgenを再度コードする必要があります。これは問題である場合とそうでない場合があります。 –

+0

私は-1に何か理由はありません。 –

0

ない簡単な回避策。

おそらく、クラス内のフィールド(プライベートとパブリック)を直列化/逆シリアル化し、それを再帰的に行いたいだけです。あなたはおそらくそれらを得るために反射を使用する必要があります。プロパティの値を設定するときに副作用が発生する可能性があるため、プロパティをデ/直列化しないでください。また、オブジェクトであるすべてのフィールドを再帰的にde/serializeする必要があります。挑戦はどこを止めるべきかを知ることです。

リフレクションを使用してシリアライズされたオブジェクトを逆シリアル化する方法について、いくつか大きな推測をする必要があります。これらのオブジェクトのフィールドのいくつかは他のオブジェクトへの参照を含んでいると仮定しなければなりません。また、それらをすべてトラバースする方法を知っておく必要があります。

また、パラメータ化されたコンストラクタを呼び出す必要があります。また、リフレクションでフィールドを設定するときに大きなダメージを与えないようにしてください。

要するに、シリアライズされた形式から独自のクラスを再作成する最良の方法であるラッパークラスの特別なセットを作成した方がよい場合があります。あなたの特別な目的のクラスを直列化できるようにすることができます。これは簡単な作業ではありません。

しかし、コードジェンは、クラス内のすべてのフィールドを識別する作業を簡略化することができます。

0

もう1つの選択肢は、アダプタパターンを使用することです。

元のクラスを変更する必要はありません。 悪いニュースは、おそらく、最初の "変更できない"クラスに存在するコードの2倍のコードを書くことになるということです。

2つの新しいクラス、アダプタと新しいserializebleクラスがあります。

アダプタは、直列化不可能なクラスを調べることによって、直列化可能なクラスを作成する方法を知っているという考えがあります。他の方法(シリアル化できないシリアル化可能)に行くには、アダプターを使用することができます(もちろん、ここで私はプライベートセッターが実際にパラメーター化されたコンストラクターを使って設定されていると仮定しています)。

Here's the pattern in detail.

0

これに2つの別個の部分がありますについて

  1. 抽出/ファイル(または他の場所)から読み出し/格納データ
  2. 設定

は最初の部分は、あなたが直列化/逆シリアル化したいクラスを変更できない場合、あなたは本当に反映を通じて深いコピーを残して残っています。

シリアル化の場合、その値を格納しているクラスの各メンバーを調べます。

XMLなどの媒体に保存したいメディアを使用し、これらの値をディスクに書き込みます。

逆シリアル化の場合、ファイルから値を読み込み、オブジェクトの新しいインスタンスを作成し、リフレクションを使用してすべての値を設定します。

すべてのメンバーを取得/設定すると、同じ状態のオブジェクトが作成されます。複雑なメンバーがいる場合は、再帰的にすべてのオブジェクトを調べる必要があります。

データをディスクに保存する方法については、xmlまたはバイナリの両方が機能します。それを見て人間が読めるようにしたい場合は、XMLを使ってください。 (デバッグがはるかに簡単になるので、最初のスタブでこれをお勧めします。)

7

...シリアル化代理のための仕事のように聞こえる!概要についてはhttp://msdn.microsoft.com/en-us/magazine/cc188950.aspx

移動します。

+0

+1:サロゲートはBinaryFormatterでうまいです。 –

+0

リンク先:https://web.archive.org/web/20141231105711/http://msdn.microsoft.com/en-us/magazine/cc188950.aspx、またはMSDN:https:// msdn。 microsoft.com/en-us/library/system.runtime.serialization.surrogateselector(v=vs.110).aspx –

0

実際には、問題の規模と必要なパフォーマンスによって異なります。

問題クラスが1つある場合は、そのクラスを直列化/逆直列化できる代理クラスを作成するだけです。 100以上のクラスについて話しているのであれば、おそらくすべての複雑さをサポートするシリアライゼーションフレームワークを使用する必要があります。パラメータのない構築は悪夢ではありません。あなたが書いたり使用するシリアライゼーションフレームワークが何であれ、コンストラクタに渡すためにparamsを知る必要があります。プライベートセッター/ディクショナリ/リストなどはあまり問題にはなりません。

BSDのMedia Browser用にmini-serializationフレームワークを書きました。パフォーマンスに重点を置いていましたが、私が使用しているテクニックはあなたの問題に適応できます。同様にMarcのprotocol buffersで使用されている技術も使用できます。

パフォーマンスが重要でない場合は、リフレクションを使用するかなり簡単なシリアライズフレームワークをかなり素早くコーディングすることができます。

関連する問題