2012-11-12 20 views
6

Kann der Teil einer Binärdatei deserialisiert werden?Teil einer Binärdatei deserialisieren

Grundsätzlich habe ich ein Objekt ähnlich wie unten, das ich in eine Binärdatei serialisieren.

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) 
} 

Was ich möchte es in der Lage sein, nur deserialisieren Name und Value durch eine ListView für die Dateiauswahl Zwecke zu bevölkern und dann den Rest der Datei deserialisiert bei Bedarf (dh der Benutzer wählt die Datei aus der ListView.

Wie immer jede Hilfe sehr dankbar und wenn alle 3rd-Party-Bibliotheken vorgeschlagen werden, müßten sie sich frei in einem kommerziellen Umfeld sein, um verwendet.

+1

könnte sich lohnen Erwähnen, wie Sie die Datei an erster Stelle serialisiert haben – musefan

+0

Hier ist eine ähnliche Frage: http://stackoverflow.com/questions/1572999/c-sharp-partial-deserialization könnte die Antwort enthalten, die Sie suchen. –

+0

Möchten Sie nur bestätigen, dass die Liste View Items Abschnitte der Binärdatei darstellen und Sie nur die Teile laden möchten, die der Benutzer auswählt? – Derek

Antwort

6

protobuf-net kann das, weil es nicht an den spezifischen Typ gebunden ist; zum Beispiel:

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

Aber wenn Sie nicht möchten, dass zwei verschiedene Typen und/oder wollen Sie nicht Attribute hinzufügen müssen - das auch getan werden kann:

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. Das ist großartig, dass Sie zwei verschiedene Modelle aus demselben Byte-Array erhalten können. Aber gibt es eine Möglichkeit, den "Rest" bei Bedarf in "Lite" zu deserialisieren? Wenn ich diese Lösung richtig verstehe, würde es erforderlich sein, dass Sie das 'lite' wegwerfen und ein ganz neues Objekt mit dem' fatModel' deserialisieren, wenn Sie das vollständige Objekt benötigen. –

+0

Also ist es im ersten Beispiel egal, für welches Objekt es sich deserialisiert, solange die Eigenschaftsnamen und -typen und die 'ProtoMember'-Werte gleich sind? –

+0

@Eren in einigen Fällen, * ja * (Protobuf ist zusammenführbar), aber im allgemeinen Fall würde ich sagen, das ist nur der falsche Ansatz. –

0

Wie über die Name setzen und Value in eine Oberklasse und serialisieren sie separat?

Alternativ können Sie ein Dictionary pflegen und dieses in eine Datei serialisieren.