【问题标题】:WCF, Interface return type and KnownTypesWCF、接口返回类型和 KnownTypes
【发布时间】:2011-05-24 09:04:02
【问题描述】:

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

合同

public interface IAtm
    {
        [DataMember]
        double Latitude { get; set; }

        [DataMember]
        double Longitude { get; set; }
    }

[ServiceContract]
    public interface IAtmFinderService
    {

        [OperationContract]
        ICollection<IAtm> GetAtms();

    }

服务实现:

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

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

的函数
object[] GetAtms();

当试图调用它时,我得到这个错误:

InnerException 消息是 'Type 带有数据合同名称的“WCFTest.Atm” 'ATM:http://schemas.datacontract.org/2004/07/WCFTest' 预计不会。考虑使用一个 DataContractResolver 或添加任何类型 不知道静态的列表 已知类型 - 例如,通过使用 KnownTypeAttribute 属性或通过 将它们添加到已知类型列表中 传递给 DataContractSerializer。'。

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

[OperationContract]
        ICollection<Atm> GetAtms();

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

【问题讨论】:

    标签: c# visual-studio wcf visual-studio-2010


    【解决方案1】:

    好的,我设法修复它 在我看来,问题是这样的

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

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

    【讨论】:

    • +1 感谢您的修复,我遇到了同样的问题,但只需要为我的自定义 PagedList 实现添加 List 实现。我的“T”是一个域对象,已经为我正确序列化了。
    猜你喜欢
    • 1970-01-01
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多