3

I want to serialize a Dictionary that has a custom IEqualityComparer.

I've tried using DataContractSerializer but I can't get the Comparer to be serialized.

I can't use BinaryFormatter because of this.

I can always do something like:

var myDictionary = new MyDictionary(deserializedDictionary, myComparer);

But that means I'd need twice the memory the dictionary uses.

Dez
  • 5,702
  • 8
  • 42
  • 51
Meidan Alon
  • 3,074
  • 7
  • 45
  • 63

2 Answers2

0

I just read the error report...

Binary serialization fails for object graphs with more than ~13.2 million objects.

if you have a graph that big, you always may have some problems.

Would you like to try an alternative serializer? "protobuf-net" is a bespoke binary serializer following Google's protocol buffers format, and may work for larger sets, especially in "group" mode.

user229044
  • 232,980
  • 40
  • 330
  • 338
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Thanks, tried it, but I keep getting an empty stream after the serialization ends. Is there anything else I should do beside marking my objects with DataContract and DataMember? – Meidan Alon Dec 15 '08 at 00:45
  • That is odd... note that with DataMember (by default) you need to specify an Order on the members, although there is a global switch for inferring the order. – Marc Gravell Dec 15 '08 at 13:27
0

Why does the custom Comparer even need to be serialized? Here is a test case that works for me.

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.IO;

public class MyKey {
    public string Name { get; set; }
    public string Id { get; set; }
}

public class MyKeyComparer :IEqualityComparer {
    public bool Equals( MyKey x, MyKey y ) {
        return x.Id.Equals( y.Id ) ;
    }
    public int GetHashCode( MyKey obj ) {
        if( obj == null ) 
            throw new ArgumentNullException();

        return ((MyKey)obj).Id.GetHashCode();
    }
}

public class MyDictionary :Dictionary {
    public MyDictionary()
        :base( new MyKeyComparer() )
    {}
}

class Program {
    static void Main( string[] args ) {
        var myDictionary = new MyDictionary();
        myDictionary.Add( new MyKey() { Name = "MyName1", Id = "MyId1" }, "MyData1" );
        myDictionary.Add( new MyKey() { Name = "MyName2", Id = "MyId2" }, "MyData2" );

        var ser = new DataContractSerializer( typeof( MyDictionary ) );

        using( FileStream writer = new FileStream( "Test.Xml", FileMode.Create ) )
            ser.WriteObject( writer, myDictionary );

        using( FileStream reader = new FileStream( "Test.Xml", FileMode.Open ) )
            myDictionary = (MyDictionary)ser.ReadObject( reader );
    }
}

jyoung
  • 5,071
  • 4
  • 30
  • 47
  • That's because ReadObject calls MyDictionary's ctor. Actually, the object I'm serializing is not the dictionary itself, but a container of several dictionaries and some more objects. It's ctor doesn't call the dictionaries' ctor, but I may be able to exploit that, thanks. – Meidan Alon Dec 15 '08 at 00:42