WCF,接口返回类型和KnownTypes

我正在创建一个WCF服务,我在一些序列化问题上遇到了很多麻烦。 也许只有一种方法可以做到这一点,但我想确认一下这是我的示例代码:

合同

public interface IAtm { [DataMember] double Latitude { get; set; } [DataMember] double Longitude { get; set; } } [ServiceContract] public interface IAtmFinderService { [OperationContract] ICollection GetAtms(); } 

服务实施:

 [KnownType(typeof(Atm))] [KnownType(typeof(List))] [ServiceKnownType(typeof(Atm))] [ServiceKnownType(typeof(List))] public class AtmFinderService : IAtmFinderService { public ICollection GetAtms() { return new List() { new Atm() { Latitude = 1, Longitude = 1 }, new Atm() { Latitude = 2, Longitude = 2 } }; } } 

我添加了所有的KnownType和ServiceKnownType属性,因为我认为那里缺少了一些东西..所以现在,我一直在做一些测试。 我尝试创建一个控制台应用程序,使用“添加服务引用”方法使VS自动创建代理。 这样,我得到了一个类似的function

 object[] GetAtms(); 

当试图调用它时,我收到此错误:

InnerException消息是’Type’WCFTest.Atm’,数据协定名称为’Atm:http://schemas.datacontract.org/2004/07/WCFTest’不是预期的。 考虑使用DataContractResolver或将任何静态未知的类型添加到已知类型列表中 – 例如,通过使用KnownTypeAttribute属性或将它们添加到传递给DataContractSerializer的已知类型列表中。

非常好……那么,我认为VS的自动生成代码就是废话。 我在我的服务(以及所有相关的类和实现)中做了以下更改:

 [OperationContract] ICollection GetAtms(); 

所以现在,我正在回归一个具体的类型。 更新服务引用后,它会创建Atm类的副本及其成员和内容。 呼叫服务后,呼叫成功。 我认为这是与自动生成的代码相关的一些不良行为,所以我尝试创建一个非常简单的主机/客户端应用程序。 我启动了一个控制台主机监听某个端口,然后创建了一个使用ClientBase类来调用该服务的客户端。 相同的行为…如果实现服务返回接口类型,则失败。 如果我改变它以返回具体类型,它可以工作。 我认为我对KnownType属性有一些问题,我必须遗漏序列化程序无法处理的东西。 但我不知道是什么。

好吧,我设法解决了这个问题,正如我所看到的,就是这个问题

由于我返回的是接口而不是具体的类,因此WCF不知道在另一端会发生什么。 所以,它可以是任何东西。 当他得到一份名单时,他很困惑。
正确的方法是在需要的地方添加KnownType属性。
谁需要知道这些类型? 服务实现,以正确地序列化和反序列化它们。 但是,客户端与服务的接口进行通信,而不是与实现本身进行通信。 这就是为什么在服务实现中添加KNownType属性不起作用的原因
这里的问题是,接口不允许KnownType属性,但它们允许ServiceKnownType属性。 该问题的解决方案是在服务接口合同中添加预期类型,瞧,一切正常并使用接口

  [ServiceContract] [ServiceKnownType(typeof(Atm))] [ServiceKnownType(typeof(List))] public interface IAtmFinderService { [OperationContract] ICollection GetAtms(); }