2011-09-08 21 views
1

オブジェクトのバイナリシリアル化ファイルを作成しました。これを他の多くのプロジェクトのデータベースファイルとして使用することができました。同じプロジェクトではうまく動作しますが、他のプロジェクトからそのファイルを逆シリアル化しようとすると、それはできません。表示されるエラーは、 "xxxx.xxxxアセンブリが見つかりません"と表示されます。オブジェクトを直列化してアセンブリを独立させるにはどうすればいいですか?.NETでの逆シリアル化の問題

は、ここに私のコードです:

  // Binary formatter 
      IFormatter formatter = new BinaryFormatter(); 
      Stream stream = new FileStream("BinarySerialization.bin", 
            FileMode.Create, 
            FileAccess.Write, FileShare.None); 
      formatter.Serialize(stream, words); 
      stream.Close(); 

私は何をする必要がありますどのような改正?実際のコードサンプル/サンプルを私に提供してください。

ありがとうございました。

+1

チェック:[この質問](http://stackoverflow.com/questions/4193951/how-to-get-binaryformatter-to-deserialize-in-a-different-次の記事を参照してください。アプリケーション) –

答えて

1

シリアル化する必要があるすべてのモデルを別々のアセンブリに配置します。 次に、モデルを逆シリアル化する必要のある場所でこのアセンブリを参照します。

何らかのジェネレータが必要ない場合は、スキーマ(WCFのユーティリティと同じ)に基づいてモデルを再作成するか、XMLなどのプレーンフォーマットを使用してデータを保持します。

+0

ここではXMLファイルは安全ではありません。ユーザーがメインデータベースファイルの内容を知りたくないからです。あなたは私にassemblyBindingやそのような他の解決策を使用する方法を教えてもらえますか? – MrClan

+0

@Pratik xmlが安全でない場合、どちらも「BinaryFormatter」ではありません。厳密には –

+0

です。アセンブリを変更するとBinaryFormatterに問題が発生しますが、これ以外にもシリアライズ/デシリアライズするすべてのクラスを置くだけですあなたはISerializableをDll-Projectに実装します)。これらのモデルを逆シリアル化またはシリアライズする必要がある場合は、参照の追加とその結果のdllを追加してください。 – Carsten

1

BinaryFormatterは、タイプベースのシリアライズされたものです。タイプメタデータを出力に深く埋め込みます。それはもはや同じTypeあるので、それは、BinaryFormatterのために十分ではないではありません(種類はそのアセンブリにバインドされている) - 私はあなたがは、プロジェクト間クラス定義をコピーしたことを賭けるだろう。

あなたのシナリオでは、ここで正しいことは契約ベースのシリアライザを使用することです。例えば:

  • XML(XmlSerializerDataContractSerializer、など)
  • JSON(JavascriptSerializer、JSON.net、など)
  • バイナリ(いるProtobufネットなど)

だろうが、そこだろうあなたのシナリオでは全部となり、より良いバージョンの許容差があります(BinaryFormatterはバージョンと非常に脆いです)

あなたは「ここではXMLは安全ではありません。ユーザがメインのデータベースファイルの内容を知りたくないからです。」 - その場合、protobuf-netは人間が判読できないという "利点"を持っていますが、これらのどれも、BinaryFormatterです。です。私がしたい場合は、私は本当に、本当にしたい場合は内容を取得することができます。強力なセキュリティが必要な場合は、適切な暗号化を使用してください。その場合、あなたのコードは(多分いくつかのマーカーの属性に加えて)次のようになります。

using(var stream = new FileStream("BinarySerialization.bin", FileMode.Create, 
           FileAccess.Write, FileShare.None)) 
{ 
    Serializer.Serialize(stream, words); 
} 

編集(コメントごとに)表示するWordは、2列のメンバーを持つクラスです(ほとんどのDictionary<string, List<Word>>をシリアル化する方法ここのコードは、完全な例を示すための配管に過ぎません):

using System; 
using System.Collections.Generic; 
using System.IO; 
using ProtoBuf; 
[ProtoContract] 
public class Word { 
    [ProtoMember(1)] 
    public string Foo { get; set; }  
    [ProtoMember(2)] 
    public string Bar { get; set; } 
} 
static class Program { 
    public static void Main() { 
     var data = new Dictionary<string, List<Word>>{ 
      {"abc", new List<Word> { 
       new Word { Foo = "def", Bar = "ghi"}, 
       new Word { Foo = "jkl", Bar = "mno"} 
      }}, 
      {"pqr", new List<Word> { 
       new Word {Foo = "stu", Bar = "vwx"} 
      }} 
     }; 
     using(var file = File.Create("my.bin")) { 
      Serializer.Serialize(file, data); 
     } 
     Dictionary<string, List<Word>> clone; 
     using(var file = File.OpenRead("my.bin")) { 
      clone = Serializer.Deserialize< 
       Dictionary<string, List<Word>>>(file); 
     } 
     foreach(var pair in clone) { 
      Console.WriteLine(pair.Key); 
      foreach(var word in pair.Value){ 
       Console.WriteLine("\t{0} | {1}", word.Foo, word.Bar); 
      } 
     }  
    } 
} 
+0

"protobuf"はうまく聞こえるが、私はそれを少し研究しなければならないので、実装するには時間がかかるだろうと思う。 – MrClan

+0

@Pratikほとんどの場合、それらの間をスワップするのはかなり簡単です。私はあなたのモデルを見ることができないので、言うことは難しいです。あなたがそれを行う方法を示すことができる代表的な例のいくつかの並べ替えを提供することができます。 –

+0

私はDictionary >型のオブジェクトを持っています。ここで、Wordは内部に2つの文字列メンバを持つ直列化可能なクラスです。だから、どうすればprotobufでこのオブジェクトをシリアライズしますか? – MrClan

1

NETは、実行時にデータをシリアライズしてデシリアライズするヘルパーDLLを作成します。まず、コンパイルされたコードファイルを吐き出し、ヘルパーdllをロードしてシリアライズとデシリアライズを行います。

何らかの理由でヘルパー.dllが作成されている間に何かが発生した場合 - コンパイルエラーとしましょう - 実行時にこのDLLが見つかりません。

あなたのケースのdllの名前がランダムな文字であれば、私はあなたが上記の問題に直面していると言います。ドキュメントの切り替えスイッチをオンにすることでこれをトラブルシューティングできます。

HOW TO: Debug into a .NET XmlSerializer Generated Assembly

関連する問題