How do you get WCF serialization to preserve a non-default Comparer on a generic Dictionary?

半城伤御伤魂 提交于 2019-12-10 23:34:15

问题


Suppose we start from scratch in Visual Studio 2010 and add a 'WCF Service Aplication'. We add this method and implementation:

// (in IService1.cs)
    [OperationContract]
    Dictionary<string, string> GetDictionary();

// (in Service1.svc.cs)
    public Dictionary<string, string> GetDictionary()
    {
        return new Dictionary<string, string>(
            StringComparer.InvariantCultureIgnoreCase);
    }

Then we add a new 'Console Application' to the same solution, add a Service Reference to our service project (using all the default settings), and add this code to Main:

        var c = new ServiceReference1.Service1Client();

        var d = c.GetDictionary();

        d.Add("key",string.Empty);
        // Since this *should* be a case-insensitive dictionary,
        // this add *should* fail
        d.Add("KEY", string.Empty);

        Console.WriteLine("Both Add()s succeeded :(");
        Console.ReadKey();

We expect this code to fall over, because a case-insensitive dictionary would regard key and KEY as the same key, and so would throw on the second Add.

Unfortunately, when everything is compiled and run, we get a sad face :(, because when the Dictionary comes across the WCF layer it 'forgets' that it was made with a specific, non-default, Comparer, and instead acquires strings default equality comparer.

Is there an easy setting to change so that the Comparer property of the Dictionary will be preserved as it goes across the wire? Or must I create a custom class?

(I've seen XML serialization of a Dictionary with a custom IEqualityComparer but it didn't offer me much enlightenment. I've also seen this codeproject comment from 3 years ago, but it is my question, not an answer)


回答1:


If you use the standard mechanism like "Add Service Reference" etc., WCF by design will create a completely separate copy of your data structures based on the structure on the wire, e.g. the XML-serialized structure that can be expressed in XML schema (XSD).

This does not include anything that's more behavior (code) rather than actual data - things like comparers etc.

There is no setting to "turn" this on - it just cannot be done. The only way to solve this - when you control both ends of the communication wire, and both are .NET platforms - is to share that common stuff both sides need (service contracts, data contracts etc.) in a separate assembly that both the server as well as the client reference. On the client, you need to make sure to add the reference to that shared assembly before creating the WCF proxy - in that case, the WCF runtime will reuse the existing data structures (like your dictionary with a custom comparer) from the shared assembly, instead of creating new, boiler-plate copies.



来源:https://stackoverflow.com/questions/8140583/how-do-you-get-wcf-serialization-to-preserve-a-non-default-comparer-on-a-generic

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!