views:

888

answers:

2

Hi,

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.

Any suggestions? Thanks.

A: 

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 serlaizer? "protobuf-net" is a bespoke binary serializer following google's protocol buffers format, and may work for larger sets, especially in "group" mode.

Marc Gravell
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
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
A: 

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
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