我对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 - 缺点是我最终会得到许多额外的OperationContracts?
答案 0 :(得分:6)
最后,我发现这篇博文在头上发了钉 -
不幸的是合同的方式 用WCF表示非常 容易忘记他们的目的是什么: 定义发送给的消息 操作并从中发回 操作。实际上你必须这样做 想“我该如何表达这些数据 用XML格式?“ XML不支持 继承所以无论你放入什么 合同将不得不有一些 映射到XML的方式。数据 用于定义消息的合同 只是一种.NET类型的便利 用于为数据生成XML 你想通过 - 如果你看到它们 你注定要用的任何其他方式 痛苦的世界。所以想想数据 你想要通过,而不是如何通过 碰巧代表你的 业务层和设计你的 DataContracts相应。
http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx
因此,我将重构以提供具有显式合同类型的其他方法。这也将允许我通过删除所有类型检查来清理服务实现。
感谢您的帮助。
答案 1 :(得分:3)
好的,第一个问题是:你为什么真的使用Message契约?你真的需要吗?
通常,只有在需要严格控制SOAP消息的布局时才会使用消息协定,例如:要满足您需要调用的遗留系统,这需要特定的标题等。
“普通”WCF呼叫几乎不需要使用消息合同。
您可以使用[ServiceContract]
定义服务调用(服务上的方法),并将数据结构传递为[DataContract]
。如果你有一个DataContract,你可以有更多选择来处理你的服务中的继承/多态(更多的是使用消息契约构造)。
马克
答案 2 :(得分:0)
是否可以更改BaseMessage以使其成为具有无参数构造函数的具体类?
错误消息告诉我们无法初始化BaseMessage类型的对象,因为它是抽象的。
答案 3 :(得分:0)
该错误只是希望您拥有一个可以使用的默认空构造函数。但是,我同意marc_s;在我参与过的项目中,我很少使用消息合同,我记得的唯一一个案例就是文件传输服务的一部分,其中文件块在messasges中传递。
答案 4 :(得分:0)
尝试使用KnownType属性装饰[ServiceContract]
。由于 TestMessage 不是来自公共操作的“可见”,这有助于管道知道在看到它时如何对待它。
如果这应该允许将[DataContract]
序列化为 TestMessage ,您仍然可能需要通过“is a
”或其他一些转换来处理多条消息。