WCF、接口返回类型和已知类型 [英] WCF, Interface return type and KnownTypes

查看:30
本文介绍了WCF、接口返回类型和已知类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm creating a WCF service, and I'm having a lot of trouble with some Serialization issues. Perhaps there's just 1 way to do it, but i'd like to confirm it Here's my sample code :

合同

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 自动创建代理.这样,我得到了一个像

I added all of the KnownType and ServiceKnownType attributes because i thought that there was something missing there.. So now, i've been doing some tests. I tried creating a console app, using the "add service reference" method to make VS create automatically the proxy. This way, I get a function like

object[] GetAtms();

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

When trying to call it, i get this error :

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

The InnerException message was 'Type 'WCFTest.Atm' with data contract name 'Atm:http://schemas.datacontract.org/2004/07/WCFTest' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'.

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

Very nice... So then, I think that VS's autogenerated code is crap. I did the following change in my service (and all the related classes and implementations) :

[OperationContract]
        ICollection<Atm> GetAtms();

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

So now, i'm returning a concrete type. After updating the service reference, it creates a copy of the Atm class, with its members and stuff. After calling the service, the call succeeds. I thought that this was some bad behaviour related to the autogenerated code, so i tried creating a very simple host/client app. I started a console host listening on some port, then created a client that uses the ClientBase class to make a call to the service. Same behaviour... if the service is implemented returning an interface type, it fails. If i change it to return the concrete type, it works. I think that i have some problem with the KnownType attributes, i must be missing something that the serializer can't process. but i don't know what.

推荐答案

好的,我已经解决了在我看来,问题是

Ok, i managed to fix it The problem, as I see it, was this

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

Since I'm returning an interface and not a concrete class, WCF doesn't know what to expect on the other end. So, it can be anything. When he gets a List, he's confused.
The correct way to do it was to add the KnownType attributes where needed.
Who needs to know those types? the service implementation, to serialize and deserialize them correctly. However, the client talks with the interface of the service, not with the implementation itself. That's why adding theKnownType attribute in the service implementation didn't work
The problem here is that, interfaces don't allow KnownType attributes, but they do allow ServiceKnownType attributes. The solution to the problem was to add the expected type in the service interface contract, and voila, everything works ok and using interfaces

    [ServiceContract]
    [ServiceKnownType(typeof(Atm))]
    [ServiceKnownType(typeof(List<Atm>))]
    public interface IAtmFinderService
    {

        [OperationContract]
        ICollection<IAtm> GetAtms();

    }

这篇关于WCF、接口返回类型和已知类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆