2010-05-03 50 views
10

我在理解WCF中的ServiceKnownType時遇到了一些麻煩。瞭解WCF中的ServiceKnownType

this blog採取下面的代碼不起作用:

[DataContract(Namespace = 「http://mycompany.com/」)] 
public class Shape{…} 

[DataContract(Namespace = 「http://mycompany.com/」)] 
public class Circle : Shape {…} 

[ServiceContract] 
public interface IMyServer 
{ 
    [OperationContract] 
    bool AddShape(Shape shape); 
} 

IMyServer client = new ChannelFactory<IMyServer>(binding, endPoint).CreateChannel(); 

client.AddShape(new Circle()); 

它不工作的原因是因爲你試圖添加一個圓,但是servicecontract只允許一個Shape。你應該對知識類型做些什麼,但是我對這是如何工作感到困惑。

由於該代碼在服務中,爲什麼它不自動知道Circle是從Shape派生的?另外,ServiceKnownType實際上做了什麼?

當ServiceKnownType置於DataContract之下時,顯然這會使其工作。我猜它說嘿,這個特殊的對象類型稱爲形狀也可以是一個圓。我無法理解爲什麼它會這樣做,因爲如果添加一個像Square這樣的新類型,您將不得不向Shape類中添加一個ServiceKnownType。如果它不能推斷它,將KnownType放到方形而不是形狀上是否有意義?所以廣場說,嘿,我是一個形狀,你不必擺弄Shape類?如果Shape類內置到庫中,並且您想創建像DiamondShape一樣的自定形狀,則無法將其添加到Shape類,因爲您無權訪問源代碼。

回答

12

問題是WCF不會進入所有程序集並嘗試查找Shape的所有可能的子類型。它也不會傳輸XML文檔的類型信息(程序集,完全限定類型名稱)。

因此,儘管在傳出的XML上生成標記「Circle」不會有問題,但傳入的反序列化器不知道如何處理。

KnownType「hack」就像已知類型的註冊表,必須由雙方執行。它是明確的。有了這個註冊表,反序列化器就知道「Circle」反序列化爲X類型,沒有任何ambiquity的機會,也無需解析派生類型的所有可用或可訪問的程序集。

記住,Square並沒有說「我是一個形狀」,它來自一個XML標籤,並且您不會輕易自動地知道要使用哪個.NET類。

+0

是不是隻需要檢查該服務的DataContracts?在這個例子中只有兩個,無論如何它可能會緩存它們。 – NibblyPig 2010-05-03 12:54:04

+0

不,因爲數據合同沒有說明哪個子類對於那個可能的調用實際上是有效的 - 或者存在哪個子類。數據合同只會說「好的,這是這個屬性的一個形狀」,而不是「共享的哪個子類來到這裏」。 – TomTom 2010-05-03 13:13:30