2012-11-12 4 views
6

バイナリファイルの一部を逆シリアル化することはできますか?バイナリファイルの一部をデシリアライズ

私はバイナリファイルにシリアル化する以下のようなオブジェクトを基本的に持っています。

public class MyObject 
{ 
    public string Name { get; set; } 

    public int Value { get; set; } 

    pubic IList<MyOtherObject> { get; set; } //lots of data in her (order of kB-MB) 
} 

は、私はファイル選択のためにListViewを移入によってのみNameValueをデシリアライズして、必要なときにファイルの残りの部分をデシリアライズできるようにしたいと思いますどのような(つまり、ユーザーはからそのファイルを選択しますListView

いつものように、任意のヘルプは大歓迎して任意のサードパーティのライブラリが提案されている場合、彼らは商業環境の中で自由に使うことができるようにする必要があります。

+1

する価値があるかもしれませんがあなたが最初にファイルをシリアライズした方法を述べてください – musefan

+0

似たような質問があります:http://stackoverflow.com/questions/1572999/c-sharp-partial-deserializationにはあなたが探している答えが含まれているかもしれません。 –

+0

確認したいだけです。リストの表示項目はバイナリファイルのセクションを表し、ユーザーが選択した部分だけをロードしますか? – Derek

答えて

6

protobuf-netは、特定のタイプに結び付けられていないため、これを実行できます。例えば:

using ProtoBuf; 
using System.Collections.Generic; 
using System.IO; 

[ProtoContract] 
public class MyOtherObject { } 
[ProtoContract] 
public class MyObject 
{ 
    [ProtoMember(1)] 
    public string Name { get; set; } 
    [ProtoMember(2)] 
    public int Value { get; set; } 
    [ProtoMember(3)] 
    public IList<MyOtherObject> Items { get; set; } 
} 

[ProtoContract] 
public class MyObjectLite 
{ 
    [ProtoMember(1)] 
    public string Name { get; set; } 
    [ProtoMember(2)] 
    public int Value { get; set; } 
} 

static class Program 
{ 
    static void Main() 
    { 
     var obj = new MyObject 
     { 
      Name = "abc", 
      Value = 123, 
      Items = new List<MyOtherObject> 
      { 
       new MyOtherObject(), 
       new MyOtherObject(), 
       new MyOtherObject(), 
       new MyOtherObject(), 
      } 
     }; 
     using (var file = File.Create("foo.bin")) 
     { 
      Serializer.Serialize(file, obj); 
     } 
     MyObjectLite lite; 
     using (var file = File.OpenRead("foo.bin")) 
     { 
      lite= Serializer.Deserialize<MyObjectLite>(file); 
     } 
    } 
} 

しかし、あなたは二つの異なるタイプを望んでいない、および/または、あなたは、属性を追加する必要はしたくない場合は - あまりにも行うことができます。

using ProtoBuf.Meta; 
using System.Collections.Generic; 
using System.IO; 

public class MyOtherObject { } 
public class MyObject 
{ 
    public string Name { get; set; } 
    public int Value { get; set; } 
    public IList<MyOtherObject> Items { get; set; } 
} 
static class Program 
{ 
    static readonly RuntimeTypeModel fatModel, liteModel; 
    static Program() 
    { 
     // configure models 
     fatModel = TypeModel.Create(); 
     fatModel.Add(typeof(MyOtherObject), false); 
     fatModel.Add(typeof(MyObject), false).Add("Name", "Value", "Items"); 
     liteModel = TypeModel.Create(); 
     liteModel.Add(typeof(MyOtherObject), false); 
     liteModel.Add(typeof(MyObject), false).Add("Name", "Value"); 
    } 
    static void Main() 
    { 
     var obj = new MyObject 
     { 
      Name = "abc", 
      Value = 123, 
      Items = new List<MyOtherObject> 
      { 
       new MyOtherObject(), 
       new MyOtherObject(), 
       new MyOtherObject(), 
       new MyOtherObject(), 
      } 
     }; 
     using (var file = File.Create("foo.bin")) 
     { 
      fatModel.Serialize(file, obj); 
     } 
     MyObject lite; 
     using (var file = File.OpenRead("foo.bin")) 
     { 
      lite = (MyObject)liteModel.Deserialize(
       file, null, typeof(MyObject)); 
     } 
    } 
} 
+1

+1。これは、同じバイト配列から2つの異なるモデルを得ることができることは素晴らしいことです。しかし、必要に応じて「残り」を「ライト」にデシリアライズする方法はありますか?私がこの解決法を正しく理解していれば、フルオブジェクトが必要なときに、 'fatModel'を使って' lite'を投げ捨て、新しいオブジェクト全体を逆直列化する必要があります。 –

+0

最初の例では、プロパティ名と型と 'ProtoMember'の値が同じである限り、どのオブジェクトを非直列化しているか気にしませんか? –

+0

場合によっては@Eren *(protobufはマージ可能ですが)一般的なケースでは間違ったアプローチです。 –

0

どうNameを置くことについてとValueをスーパークラスに追加し、それらを別々にシリアライズしますか?

また、辞書を保持して、それを1つのファイルにシリアル化することもできます。

関連する問題