2012-11-12 15 views
6

Czy można deserializować część pliku binarnego?Deserializacja części pliku binarnego

Zasadniczo mam obiekt podobny do poniższego, który serializuje do pliku binarnego.

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

Chciałbym to aby móc deserializowania tylko Name i Value drodze zapełnianie ListView dla celów selekcji plik, a następnie deserializowania resztę pliku w razie potrzeby (czyli użytkownik wybierze ten plik z ListView.

Jak zawsze, każda pomoc mile widziana, a jeśli jakieś 3rd biblioteki podmiotami są sugerowane będą potrzebować, aby móc być swobodnie wykorzystywane w środowisku komercyjnym.

+1

Może warto wspominając, jak serializowałeś plik w pierwszej kolejności. – musefan

+0

Oto podobne pytanie: http://stackoverflow.com/questions/1572999/c-sharp-partial-deserialization może zawierać odpowiedź, której szukasz. –

+0

Po prostu chcesz potwierdzić, Lista Zobacz elementy reprezentują sekcje pliku binarnego, a chcesz tylko załadować te części, które wybierze użytkownik? – Derek

Odpowiedz

6

protobuf-net może to zrobić, ponieważ nie jest związany z określonym typem; na przykład:

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

Ale jeśli nie chcesz dwa różne typy i/lub nie chcą mieć, aby dodać atrybuty - które można zrobić za:

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. To świetnie, że można uzyskać dwa różne modele z tej samej tablicy bajtów. Ale czy istnieje sposób, aby w razie potrzeby odserializować "odpoczynek" w "lite"? Jeśli poprawnie zrozumiem to rozwiązanie, to wymagałoby to odrzucenia 'lite' i deserializacji całego nowego obiektu za pomocą' fatModel', gdy potrzebujesz pełnego obiektu. –

+0

Tak więc w pierwszym przykładzie nie obchodzi, do którego obiektu jest przekształcana, tak długo jak nazwy i typy właściwości, a wartości 'ProtoMember' są takie same? –

+0

@Eren w niektórych przypadkach, * tak * (protobuf jest łączony), ale w ogólnym przypadku powiedziałbym, że to po prostu niewłaściwe podejście. –

0

Jak o oddanie Name i Value do superklasy i serializuje je osobno?

Ewentualnie możesz zachować słownik i szeregować go w jednym pliku.