根据互联网上有关服务引用的人的建议,我现在摆脱了它们,并将服务/数据合约拆分为可由服务器和客户端访问的通用程序集。总的来说,这似乎工作得很好。共享数据合同的子类型
然而,我试图在服务中使用自定义对象或自定义子类型时遇到问题。起初我只想将通用程序集中的接口定义为数据的契约。我很快就知道这不会起作用,因为客户端需要一个具体的类来从服务接收对象时实例化对象。所以代替我用一个简单的类代替,基本上是这样的:
// (defined in the common assembly)
public class TestObject
{
public string Value { get; set; }
}
然后在服务合同(接口),I有一个返回这样的对象的方法。
现在,如果我只是在服务实现中创建这样一个对象并返回它,它就可以工作。不过,我想在服务(或底层业务逻辑)中定义它的一个子类型,它定义了更多的东西(例如数据库访问的方法,或者只是一些对这些对象有效的方法)。
所以为了简单起见,亚型看起来是这样的:
// (defined on the server)
public class DbTestObject : TestObject
{
public string Value { get; set; }
public DbTestObject(string val)
{
Value = val;
}
}
而且在服务上,而不是创建一个TestObject
,我创建的亚型,并将其返回:
public TestObject GetTestObject()
{
return new DbTestObject("foobar");
}
如果我运行这现在,并使客户端电话GetTestObject
,然后我立即得到一个CommunicationException
与以下错误文本:“套接字连接被中止。这可能是由处理您的消息时出错或远程主机超出接收超时或基础网络资源问题引起的。本地套接字超时时间为'00:09:59.9380000'。“
我已经发现,原因是客户端不知道如何反序列化DbTestObject
。一种解决方案是使用KnownTypeAttribute
声明基类型以使其知道子类型。但是这需要将子类型转移到常用程序集中,这当然是我想要避免的,因为我希望逻辑与客户端分离。
有没有办法告诉客户只使用TestObject
类型进行反序列化;或者解决方案是否会使用数据传输对象?
如果您在使用基于消息的WCF框架时尝试应用OO概念(如继承),那么您正在游泳。使用DTO通常是在使用WCF服务传输数据时的最佳实践,它们更贴近消息传递隐喻。 – 2012-03-27 16:56:18
@SixtoSaez我也这么认为,但是当你以前没有去过它时很难正确地进入它::/ – poke 2012-03-27 19:49:14
严格地说,如果你实现一个[自定义序列化扩展],你可以控制WCF如何序列化你的对象类型, (http://code.msdn.microsoft.com/windowsdesktop/WCF-Custom-Serialization-43b3ee7a)用于实例化您的类型实例。我不知道如何描述自定义序列化器的继承链(可能通过属性),但它应该是可能的。同样,你强迫继承消息交换模式,但如果意志坚强...... :) – 2012-03-27 20:16:29