1

I'm trying to serialize Dictionary<int, int> as Dictionary<string, string>.

So I've created Test2 type from Dictionary<int, int> as follows:

    [Serializable]
    internal sealed class Test2 : Dictionary<int, int>
    {
        internal Test2()
        {
        }

        private Test2(SerializationInfo info, StreamingContext context)
        {
            var data = (Dictionary<string, string>)
                       info.GetValue("data", typeof(Dictionary<string, string>));
            foreach (var item in data)
                Add(int.Parse(item.Key), int.Parse(item.Value));
        }

        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            var data = new Dictionary<string, string>();
            foreach (var item in this)
                data[item.Key.ToString()] = item.Value.ToString();
            info.AddValue("data", data, typeof(Dictionary<string, string>));
        }
    }

and use the following code to test the serialization:

        var test2 = new Test2 {{10, 10}};
        var formatter = new BinaryFormatter();
        using (var stream = new MemoryStream())
        {
            formatter.Serialize(stream, test2);
            stream.Position = 0;
            var clone = (Test2) formatter.Deserialize(stream);
        }

For some reason the clone does not contains any data (Count eq to 0).

Update:

"int" and "string" are here only for testing. In the real application I use something like Primary Key instead of string and big object instead of int and the serialized array contains relations between them. By cutting down the unrelated code and replacing the types I end up with with the example above.

I can only use .NET framework features.

Alex Netkachov
  • 13,172
  • 6
  • 53
  • 85
  • 2
    Your first problem is this: "I'm trying to serialize Dictionary as Dictionary". Why would you want to do such a thing!? – Chris Shain Feb 15 '12 at 17:30
  • Are you shure your private constructor is called? Maybe you could try to make it public like in this example: http://msdn.microsoft.com/en-us/library/ms182315%28v=vs.80%29.aspx – Winfried Lötzsch Feb 15 '12 at 17:54
  • @Chris Shain: I have two collections with big objects and one collection that contains links between them (as references to such objects). And I want to serialize the linking collection but use IDs of the objects instead of the objects. – Alex Netkachov Feb 15 '12 at 18:30
  • @selen: It is called. When I place the breakpoint in this method Visual Studio stops on it. – Alex Netkachov Feb 15 '12 at 18:31

1 Answers1

0

There is no need for you to convert integers to strings during serialization or define your own serializable class - the framework takes care of that for you. This code (modified from this question) will do what you want just fine:

var test2 = new Dictionary<int, int> { { 10, 10 } } ;
var formatter = new BinaryFormatter();
using (MemoryStream stream = new MemoryStream())
{
    formatter.Serialize(stream, test2);
    stream.Position = 0;
    var clone = (Dictionary<int, int>) formatter.Deserialize(stream);
}

I'm uncertain why your original code didn't work, but I think it has something to do with the SerializationInfo collection being unable to serialize/deserialize dictionaries correctly. I replaced your class with this code that uses List<Tuple<string,string>> in place of Dictionary<string,string> and it works fine:

[Serializable]
internal sealed class Test2 : Dictionary<int, int>
{
    internal Test2()
    {
    }

    private Test2(SerializationInfo info, StreamingContext context)
    {
        var data = (List<Tuple<string, string>>)
                   info.GetValue("data", typeof(List<Tuple<string, string>>));
        foreach (var item in data)
            Add(int.Parse(item.Item1), int.Parse(item.Item2));
    }

    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        var data = new List<Tuple<string, string>>();
        foreach (var item in this)
            data.Add(Tuple.Create(item.Key.ToString(), item.Value.ToString()));
        info.AddValue("data", data, typeof(List<Tuple<string, string>>));
    }
}
Community
  • 1
  • 1
Chiara Coetzee
  • 4,201
  • 1
  • 24
  • 20
  • Thanks Derrick. I've updated the initial question with the explanation. In shot - I want to write the primary keys of the stored objects and restore them by replacing PKs with the real objects. As for Tuple - I cannot use it, because I should use .NET 2.0 but will try to use KeyValuePair instead of Tuple. – Alex Netkachov Feb 15 '12 at 18:35
  • Thanks. Replacing Dictionary with List> make the code working. – Alex Netkachov Feb 16 '12 at 11:34