5

Given the following classes,

public static void Test()
{
  var bigDictionary = new Dictionary<string, TestClass>();
  bigDictionary.Add("entry1", new TestClass());
  bigDictionary.Add("entry2", new TestClass());
  bigDictionary.Add("entry3", new TestClass());

  // EDIT: Added these lines
  bigDictionary["entry1"].MyDictionary.Add(1, new SecondTestClass() { MyVar = "hello" });
  bigDictionary["entry1"].MyDictionary.Add(2, new SecondTestClass() { MyVar = "world" });
  bigDictionary["entry2"].MyDictionary.Add(1, new SecondTestClass() { MyVar = "please" });
  bigDictionary["entry2"].MyDictionary.Add(2, new SecondTestClass() { MyVar = "work" });

  using (var file = System.IO.File.Create("test.temp"))
  {
    ProtoBuf.Serializer.Serialize(file, bigDictionary);
  }

  Dictionary<string, TestClass> outDict = null;
  using (var file = System.IO.File.OpenRead("test.temp"))
  {
    outDict = ProtoBuf.Serializer.Deserialize<Dictionary<string, TestClass>>(file);
  }

  // EDIT: You'll notice these asserts fail
  System.Diagnostics.Debug.Assert(outDict["entry1"].MyDictionary.ContainsKey(1));
  System.Diagnostics.Debug.Assert(outDict["entry1"].MyDictionary.ContainsKey(2));
  System.Diagnostics.Debug.Assert(outDict["entry2"].MyDictionary.ContainsKey(1));
  System.Diagnostics.Debug.Assert(outDict["entry2"].MyDictionary.ContainsKey(2));

}

[System.Runtime.Serialization.DataContract]
public class TestClass
{
  public TestClass()
  {
    MyDictionary = new Dictionary<int,SecondTestClass>();
  }

  [System.Runtime.Serialization.DataMember]
  public Dictionary<int, SecondTestClass> MyDictionary { get; set; }
}

[System.Runtime.Serialization.DataContract]
public class SecondTestClass
{
  [System.Runtime.Serialization.DataMember]
  public string MyVar { get; set; }
}

(How) can I get bigDictionary to serialize without throwing the following exception?

"Only data-contract classes (and lists/arrays of such) can be processed (error processing Dictionary`2)"

(I have tried tagging with DataContract/DataMember ProtoContract/ProtoMember etc. but nothing seems to work)

Thanks in advance for any help.

EDIT: Seems I have kinda worked it out. Given the above edited code, you'll notice the asserts fail. So it would seem that the inner dictionary is not being serialized at all. However, if I change the DataContract tags to Protobuf.ProtoContract (and DataMember to ProtoMember), it correctly picks up the inner dictionary.

Am I mis-using the library or is this a bug?

mike
  • 3,146
  • 5
  • 32
  • 46
  • I will try to look at this later today, but from memory that should (more or less) work fine... – Marc Gravell Apr 06 '11 at 09:48
  • See my edit for additional information. – mike Apr 06 '11 at 22:59
  • Further investigation shows that because one of my classes had an object variable, this was causing the serialization to fail. The exception message was just misleading. – mike Apr 06 '11 at 23:27
  • One final comment re: objects if you have time to answer. Is http://stackoverflow.com/questions/923977/protobuf-and-listobject-how-to-serialize-deserialize still the accepted solution to getting around this scenario, or is there a 'cleaner' way to do things? Thanks. – mike Apr 07 '11 at 00:08
  • There is support for this in the v2 code available to self-build; http://marcgravell.blogspot.com/2011/03/objects-graphs-and-all-that-jazz.html – Marc Gravell Apr 07 '11 at 06:00

2 Answers2

1

The answer is that the exception being thrown was a little misleading, it was a serialization error of an object in the dictionary not the dictionary itself. The actual implementation I was dealing with was a little more complex than the example I gave, and as such had a variable of type object which was breaking it.

mike
  • 3,146
  • 5
  • 32
  • 46
0

From what I know, DataContract / DataMember is heavily used in WCF contracts (at least, that's what I know it from). You could also look into the [Serializable] attribute, which might be better suited in your case.

Cheers, Perry

Flawless
  • 127
  • 7