2012-04-06 6 views
3

Ich versuche, den Serializer in einem vorhandenen WCF net.tcp-Projekt zu ändern, das freigegebene Entitäten auf Client & Server verwendet. Ich habe eine harte Zeit herauszufinden, protobuf-net (V2480) Das Diagramm here sagt, ich kann private Mitglieder serialisieren, aber kann keine Dokumentation finden, das zu tun, ist es möglich, ohne Attribute? Wie aktiviere ich den Grafikmodus (als Referenz) wie beschrieben? hereUnterschiede mit BinaryFormatter

Wird das das Problem des Auslösens des Flags für geänderte Objekte durch protobuf lösen?

Zum Beispiel habe ich eine Klasse
public enum FirstEnum 
{ 
    First = 0, 
    Second, 
    Third 
} 
public enum AnotherEnum 
{ 
    AE1 = 0, 
    AE2, 
    AE3 
} 
[Serializable()] 
public class SomeClass 
{ 
    public int SomeClassId { get; set; } 
    public FirstEnum FEnum { get; set; } 
    public AnotherEnum AEnum { get; set; } 
    string thing; 
    public string Thing 
    { 
     get{return thing;} 
     set 
     { 
      if (string.IsNullOrEmpty(value)) 
       throw new ArgumentNullException("Thing"); 

      thing = value; 
     } 
    } 

    private decimal firstAmount; 
    public decimal FirstAmount 
    { 
     get{return firstAmount;} 
     set 
     { 
      if (value != firstAmount) 
      { 
       firstAmount = value; 
       changedItems.Add("FirstAmount changed"); 
      } 
     } 
    } 
    private decimal secondAmount; 
    public decimal SecondAmount 
    { 
     get { return secondAmount; } 
     set 
     { 
      if (value != secondAmount) 
      { 
       secondAmount = value; 
       changedItems.Add("SecondAmount changed"); 
      } 
     } 
    } 
    public decimal ThirdAmount { get { return SecondAmount - FirstAmount; } } 
    public DateTime? SomeDate { get; set; } 

    private List<string> changedItems = new List<string>(); 
    public List<string> ChangedItems 
    { 
     get { return changedItems; } 
    } 
public int PrivateSet { get; private set; } 
    public SomeClass() { } 

    public SomeClass(decimal first, decimal second) 
    { 
     FirstAmount = first; 
     SecondAmount = second; 
    } 

    public void ClearChangedItems() 
    { 
     changedItems.Clear(); 
    } 

Als ich deserialisieren es mit (1000 Artikel)

var model = CreateModel(); 
items = (List<SomeClass>)model.Deserialize(returnStream, null, typeof(List<SomeClass>)); 

2012-04-06 09: 14: 28,1222 | DEBUG | ProtobufTEsts.Form1 | protobuf Anzahl geändert Artikel: 1000

Mit BinaryForrmatter

System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
items = (List<SomeClass>)binaryFormatter.Deserialize(returnStream); 

2012-04-06 09: 14: 28,1662 | DEBUG | ProtobufTEsts.F orm1 | BinaryFormatter Anzahl der geänderten Elemente: 0

Gibt es eine Möglichkeit, dass sich protobuf wie das binaryFormatter verhält, aber die Leistung von protobuf erhält?

Wie für private Serialisierung ermöglichen, schlägt diese

public static TypeModel CreateModel() 
    { 
     RuntimeTypeModel model = TypeModel.Create(); 
     ///var metaType = RuntimeTypeModel.Default.Add(typeof(SomeClass), false); 
     model.Add(typeof(SomeClass), false) 
      .Add(1, "SomeClassId") 
      .Add(2, "FEnum") 
      .Add(3, "AEnum") 
      .Add(4, "Thing") 
      .Add(5, "FirstAmount") 
      .Add(6, "SecondAmount") 
      .Add(7, "SomeDate") 
      .Add(8, "PrivateSet"); 
     TypeModel compiled = model.Compile(); 
     return compiled; 
    } 
+0

Re AsReference - IIRC (wieder, immer noch nicht an einem PC) gibt es eine Variante von MetaType.Add, die das ValueMember zurückgibt; Dies hat den AsReference-Schalter (und viele andere Optionen) darauf. –

Antwort

2

Ah, ich verstehe das Problem jetzt; Diese Linie ist problematisch:

TypeModel compiled = model.Compile(); 
return compiled; 

Wenn Sie Compile() verwenden, ist es eine formale Anordnung schafft (im Speicher), die die üblichen Regeln der Baugruppen zu gehorchen hat, insbesondere: Mitglied Zugänglichkeit. Dies bedeutet, dass es nicht auf Ihren privaten Server zugreifen kann.

Verwenden Sie stattdessen:

model.CompileInPlace(); 
return model; 

führt eine Teilzusammenstellung, aber weiterhin mit Dynamic. Dieses freche, kleine Tier hat die Möglichkeit, sich an Barrierefreiheitsregeln vorbeizuarbeiten (ähnlich wie bei der Reflektion), so dass es weiterhin den privaten Setter verwenden kann.

Beachten Sie, dass das Modell auch an Ort und Stelle kompiliert wird (auf einer detaillierteren Ebene) auf als nach Bedarf, so dass dieser Aufruf CompileInPlace ist nicht unbedingt notwendig, hilft aber alles tun, up-front ein in voraus.

Der Vollständigkeit, gibt es eine zusätzliche Compilieren (string, Zeichenkette) Überladung, die verwendet werden können, eine separate Serialisierung dll auf der Festplatte zu erzeugen, auf die verwiesen werden kann und verwendet werden, ohne irgendeine meta-Programmierung zur Laufzeit.

0

Ja protobuf-net private Felder serialisiert werden können, und zwar ohne Attribute. Ich bin nicht auf einem PC, so kann dieses Zwicken müssen:

var metaType = RuntimeTypeModel.Default.Add(typeof(SomeClass), false); 
// for each field in a known order 
metaType.Add(fieldName, someUniqueTag); 

In Attribut gesteuerte Nutzung gibt es auch ImplicitFields.AllFields, die automatisch für die Verwendung konfigurieren würden Sie beabsichtigen, aber ich habe noch nicht eine ImplicitFields-Hilfsmethode zu MetaType hinzugefügt. Ich werde das zu meiner Liste hinzufügen!

Hinweis: Tag (= Feld) Nummern sind wichtig für Protobuf und es muss möglich sein, die gleichen Zahlenzuordnungen zu reproduzieren, wenn Sie die Deserialisierung durchführen.

Eine weitere Option, die Sie in Betracht ziehen sollten, ist die (De-) Serialisierungsrückruffunktion, mit der Sie feststellen können, dass sie derzeit serialisiert/deserialisiert wird (über Vorher/Nachher-Methode). Dies kann eine andere Möglichkeit sein, Nebeneffekte für ein Intervall wie die Deserialisierung zu deaktivieren.

+0

@Mark, thx, Wie gehe ich von MetaType zu RuntimeTypeModel? Ich habe den createModel-Code über – Eric

+0

@Eric nicht an einem PC hinzugefügt ... Gibt es ein .Model? –

+0

Nein, nur was in der CreateModel-Methode erstellt wird, die ich in Bearbeitung hinzugefügt habe, muss ich etwas anderes tun? – Eric