2

假设我们在 Visual Studio 2010 中从头开始并添加一个“WCF 服务应用程序”。我们添加这个方法和实现:

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

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

然后我们向同一个解决方案添加一个新的“控制台应用程序”,向我们的服务项目添加一个服务引用(使用所有默认设置),并将此代码添加到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();

我们预计这段代码会失败,因为不区分大小写的字典会将keyandKEY视为同一个键,因此会抛出第二个Add.

不幸的是,当所有东西都编译并运行时,我们会看到一张悲伤的脸:(,因为当Dictionary遇到 WCF 层时,它会“忘记”它是使用特定的、非默认的,Comparer而是获取string默认的相等比较器。

是否有一个简单的设置可以更改,以便在穿过电线时保留其Comparer属性?Dictionary或者我必须创建一个自定义类?

(我已经看到了带有自定义 IEqualityComparer 的 Dictionary 的 XML 序列化,但它并没有给我太多启发。我还看到了 3 年前的这个 codeproject 评论,但这是我的问题,而不是答案)

4

1 回答 1

6

如果您使用“添加服务引用”等标准机制,WCF将根据设计创建一个完全独立的数据结构副本,该副本基于网络上的结构,例如可以用 XML 模式表示的 XML序列化结构( XSD)。

这不包括任何更多的行为(代码)而不是实际数据——比如比较器等。

没有设置可以“打开”它 - 它只是无法完成。解决此问题的唯一方法 - 当您控制通信线的两端,并且两者都是 .NET 平台时 - 是在一个单独的程序集中共享双方需要的共同内容(服务合同,数据合同等),服务器以及客户参考。在客户端上,您需要确保在创建 WCF 代理之前添加对该共享程序集的引用- 在这种情况下,WCF 运行时将重用来自共享程序集的现有数据结构(例如带有自定义比较器的字典),而不是创建新的样板副本。

于 2011-11-15T17:44:50.670 回答