根據互聯網上有關服務引用的人的建議,我現在擺脫了它們,並將服務/數據合約拆分爲可由服務器和客戶端訪問的通用程序集。總的來說,這似乎工作得很好。共享數據合同的子類型
然而,我試圖在服務中使用自定義對象或自定義子類型時遇到問題。起初我只想將通用程序集中的接口定義爲數據的契約。我很快就知道這不會起作用,因爲客戶端需要一個具體的類來從服務接收對象時實例化對象。所以代替我用一個簡單的類代替,基本上是這樣的:
// (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