WCF:接口、泛型和 ServiceKnownType [英] WCF: Interfaces, Generics and ServiceKnownType

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

问题描述

我有以下几点:

[ServiceContract]
[ServiceKnownType(typeof(ActionParameters))]
[ServiceKnownType(typeof(SportProgram))]
[ServiceKnownType(typeof(ActionResult<SportProgram>))]
public interface ISportProgramBl  
{
    [OperationContract]
    IActionResult<ISportProgram> Get(IActionParameters parameters);
}

当我运行 Get 方法时,出现以下错误:

When I run the Get method I get the following error:

尝试序列化参数 http://tempuri.org/:GetResult 时出错.InnerException 消息是 'Type 'PPS.Core.DomainModel.Support.Action.ActionResult`1[ [PPS.Core.DomainModel.SportProgram.ISportProgram, PPS.Core.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' 与数据协定名称 'ActionResultOfanyType: http://schemas.datacontract.org/2004/07/PPS.Core.DomainModel.Support.Action' 不是预期的.将任何静态未知的类型添加到已知类型列表中 - 例如,通过使用 knownTypeAttribute 属性或将它们添加到传递给 DataContractSerializer 的已知类型列表中.请参阅 InnerException 了解更多详情.

There was an error while trying to serialize parameter http://tempuri.org/:GetResult. The InnerException message was 'Type 'PPS.Core.DomainModel.Support.Action.ActionResult`1[ [PPS.Core.DomainModel.SportProgram.ISportProgram, PPS.Core.DomainModel, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' with data contract name 'ActionResultOfanyType: http://schemas.datacontract.org/2004/07/PPS.Core.DomainModel.Support.Action' is not expected. 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.'. Please see InnerException for more details.

从这个错误中,我可以看到它可以解析 ActionResult 但它无法解析 ISportProgram,即使我的服务界面上有 ServiceKnownType(typeof(ActionResult < SportProgram >))...

From this error I can see that it can resolve ActionResult but it can't resolve ISportProgram even though I have ServiceKnownType(typeof(ActionResult < SportProgram >)) on my service interface...

注意这是生成的引用存根看起来像这样,所以我可以看到已知类型被正确引入:

Note this is the Reference stub that is generated looks like this, so I can see that the known types are being brought across correctly:

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="SportProgramStb.ISportProgramBl")]
public interface ISportProgramBl {

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ISportProgramBl/Get", ReplyAction="http://tempuri.org/ISportProgramBl/GetResponse")]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.SportProgram.SportProgram))]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionParameters))]
    [System.ServiceModel.ServiceKnownTypeAttribute(typeof(PPS.Core.DomainModel.Support.Action.ActionResult<PPS.Core.DomainModel.SportProgram.SportProgram>))]
    object Get(object parameters);
}

为什么会出错????请注意它正确地通过 WCF 服务......但它在返回结果时抛出异常.

Why is this going wrong???? Note its getting through the WCF service correctly... but it throws the exception when the result is returned.

最后的 ActionResult 看起来像这样:

Lastly ActionResult looks like this:

public interface IActionResult<T> 
{
    T Result { get; set; } 
}

干杯安东尼

推荐答案

好吧,我认为这是 SOA 与 OOP阻抗不匹配"的另一个案例.两个世界完全不同.

Well, I think this is another case of the SOA vs. OOP "impedance mismatch". The two world are quite separate.

在 WCF 中,从客户端传递到服务器的所有内容都作为序列化消息传递 - 没有使用引用.

In WCF, all that is being passed from the client to the server is passed as serialized messages - no references are being used.

这意味着:您想在客户端序列化的所有内容,将其发送到服务器,然后反序列化并在那里使用,必须具体 - 您不能传递接口,不能使用未解决的"泛型 - 您需要将其拼写出来.基本上,从客户端通过线路传递到服务器的所有内容都必须以 XML 模式表示.

This means: everything you want to serialize on the client, send it across to the server, and deserialize it and use it there, must be concrete - you cannot pass around interfaces, you cannot use "non-resolved" generics - you need to spell it out. Basically, all that's being passed from client over the wire to the server must be expressable in XML schema.

这有很多含义:

  • 没有接口——你不能传递接口——你需要使用具体的类型
  • 没有自动"继承——你不能仅仅定义一个基类并基于它传递派生类——那些也需要被指定(这就是 ServiceKnownType 属性的用途)
  • 没有自动泛型 - 同样,您需要使用具体类型来代替

这听起来可能有很多限制 - 但这是因为 WCF 使用所有基于消息的通信 - 它无法处理引用、继承、泛型等 - 您需要将其详细说明.

This may sound like a lot of restrictions - but it's because WCF is using all message-based communication - it cannot deal with refereces, inheritance, generics etc. - you need to spell it out.

所以我本身并没有真正的答案 - 我只是认为您需要重新考虑您的策略并改变您的客户端和服务器通过 WCF 交换信息的方式.

So I don't really have an answer for you per se - I just think you need to rethink your strategy and change the way your client and server are exchanging information over WCF.

马克

PS:我做了更多的研究,与我的理解相反,似乎有一种方法可以序列化基于接口和/或抽象基类的任何东西,只要你能确定它是线路的两端始终只有 .NET(即它不能与 Java 等互操作).

PS: I did some more research, and contrary to all my understanding, there seems to be a way to serialize anything that's based on an interface and/or abstract base class across the wire, as long as you can be sure it's always only .NET on either end of the wire (i.e. it's not interoperable with e.g. Java).

请参阅关于 NetDataContractSerializer 的 Aaron Skonnard 博客文章 和另一篇 博客文章又一个展示了如何使用 NetDataContractSerializer 来将诸如 IPerson 之类的东西作为参数传递给您的方法.

See Aaron Skonnard blog post on the NetDataContractSerializer and another blog post and yet another showing how to use the NetDataContractSerializer to be able to pass around things like IPerson as parameters to your methods.

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

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