5

我对 WCF 相当陌生,只是对如何正确获取 MessageContract 继承有疑问。我的设置的简化版本如下 - 一个“基本”消息类型,然后是另一个继承自它的“测试”消息。

[MessageContract]
public abstract class BaseMessage
{ }

[MessageContract]
public class TestMessage : BaseMessage
{ }

然后,我在 ServiceContract 上有一个异步 OperationContract,定义为:

[OperationContract(AsyncPattern = true)]
IAsyncResult BeginFindRequest(BaseMessage request, AsyncCallback callback, object asyncState);

我遇到的问题是,当调用 BeginFindRequest 方法并为请求参数传入 TestMessage 实例时,WCF 框架将 TestMessage 实例反序列化为服务/服务器端的 BaseMessage。由于这被定义为抽象类,因此会导致以下错误:

“消息无法反序列化为 MessageContract 类型 BaseMessage,因为它没有默认(无参数)构造函数。”

从我可以找到的关于 MessageContract 继承的有限信息来看,它似乎应该可以工作。

所以我的问题是——为了让它发挥作用,我缺少什么;或者我是否应该在 ServiceContract 上专门为该类型定义一个单独的 OperationContract - 缺点是我最终可能会得到许多额外的 OperationContract?

4

5 回答 5

6

最后,我发现这篇博文一针见血——

不幸的是,合同在 WCF 中的表达方式很容易忘记它们的目的:定义发送到操作的消息以及从操作返回的消息。实际上,您必须考虑“我将如何在 XML 中表达这些数据?”。XML 不支持继承,因此无论您在合同中添加什么,都必须有某种方式映射到 XML。用于定义消息的数据契约只是一种 .NET 类型的便利,用于为您想要传递的数据生成 XML——如果您以任何其他方式查看它们,您注定会陷入痛苦的世界。因此,请考虑您要传递的数据,而不是它在业务层中的表示方式,并相应地设计您的 DataContracts。

http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx

因此,我将进行重构以提供具有显式合同类型的附加方法。这也将允许我通过删除所有类型检查来清理服务实现。

感谢您的帮助。

于 2009-08-24T14:42:11.667 回答
3

好的,第一个问题是:你为什么真的使用消息合约?你真的有这个需要吗??

通常,仅当您需要严格控制 SOAP 消息的布局时才使用消息协定,例如,为了满足您需要调用的需要特定标头等的遗留系统。

“正常”的 WCF 调用几乎不需要使用消息协定。

您使用 定义服务调用(服务上的方法)[ServiceContract],并将数据结构作为[DataContract]. 如果你有一个 DataContract,你有更多的选择来处理你的服务中的继承/多态性(比消息契约结构更多)。

马克

于 2009-08-24T09:45:41.477 回答
0

Try decorating your [ServiceContract] with the KnownType attribute. Since TestMessage is not 'visible' from a public operation, this helps the plumbing know how to treat it when it sees it.

If this should allow the [DataContract] to be serialized as a TestMessage your still likely to need to handle multiple messages differently via 'is a' or some other casting.

于 2009-08-24T11:34:11.070 回答
0

该错误只是希望您拥有一个可以使用的默认空构造函数。但是,我同意 marc_s;在我从事的项目中,我很少使用消息契约,我记得的唯一情况是作为文件传输服务的一部分,其中文件块在消息中传递。

于 2009-08-24T09:52:56.577 回答
0

是否可以更改 BaseMessage 使其成为具有无参数构造函数的具体类?

错误消息告诉我们无法初始化 BaseMessage 类型的对象,因为它是抽象的。

于 2009-08-24T09:26:55.537 回答