2009-05-03 7 views
2

Gibt es eine Möglichkeit in C#, eine Struktur zu einem binären Stream (MemoryStream) serialisieren, so dass die binäre Darstellung entspricht wie die Struktur visuell (d. H. Keine Auffüllung)?Serialize Struct im binären, gepackten Format

In C/C++ verwenden Sie die # Pragma-Befehle, um dem Compiler mitzuteilen, die Strukturen so zu packen, dass zwischen den Feldern kein Padding vorhanden ist. Dies ist hilfreich, wenn Sie mit zwei Apps Nachrichten über Sockets senden. Wenn das Packing deaktiviert ist, können Sie einfach den Inhalt der Struktur über den Socket "senden" und müssen sich nicht darum sorgen, jedes Feld einzeln in einen binären Puffer zu packen (müssen Sie bei Bedarf auch einen Endian-Swapping durchführen).

Antwort

2

Nicht, wenn Sie nicht sicheren Code verwenden. Verwenden Sie Protokollpuffer oder Thrift oder etwas Ähnliches; Ich würde nicht empfehlen, .NET eingebaute binäre Serialisierung basierend auf meiner Erfahrung. Sie können auch serialisieren/deserialisieren mit BinaryWriter/BinaryReader (verwenden Sie Reflektion oder Serialisierungscode vorgenerieren). Wie beim Packen können Sie es mit dem Attribut [StructLayout] steuern.

+0

Für Informationen - protobuf-net structs nicht unterstützt (nur Klassen), und ich bin mir ziemlich sicher dotnet-protobufs auch nicht. Ich weiß nichts über Thrift. –

1

können Sie verwenden, um die [StructLayout] und [FieldOffset] Attribute die Art und Weise Felder Ihre Struktur ist zu kontrollieren sind (google ‚Rangieren‘ für weitere Informationen) gepackt, und dann wird die folgende verwenden, um eine binäre Darstellung Ihrer Struktur zu erzeugen, die Ihre gesendet werden können durch Netzwerk-Stream:

public static byte[] GetBytes<TStruct>(TStruct data) where TStruct : struct 
{ 
    int structSize = Marshal.SizeOf(typeof(TStruct)); 
    byte[] buffer = new byte[structSize]; 
    GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); 
    Marshal.StructureToPtr(data, handle.AddrOfPinnedObject(), false); 
    handle.Free(); 
    return buffer; 
} 

Die Nachteile:

  • Sein nicht idiomatischen .NET
  • Sie müssen nicht verwalteten Code Berechtigungen
  • Die Pinning-Puffer könnte die Leistung auswirken
  • Ihre Struktur kann keine Referenzen haben (es spezielle Fälle für Strings und Arrays sind)