2012-11-17 129 views
2

我有以下結構:WCF調用失敗

public class DerivedClass : List<BaseClass> 
{ 
    //Some helper methods used against the List of BaseClass properties 

    //Methods 
    public List<BaseClass> GetListOfBaseClasses() 
    { 
     return (List<BaseClass>)this; 
    } 
} 

我的WCF服務所知道的BaseClass的對象,但客戶端導出它作爲一個通用的清單,現在當我嘗試調用服務,像這樣:

DerivedClass classD; 
FillData(classD) 
List<BaseClass> baseClassList = classD.GetListOfBaseClasses(); 

using (IService myService = ObjectFactory.GetMyService()) 
{ 
     myService.DoSomething(baseClassList); //Method is expecting "List<BaseClass>" 
} 

我得到以下異常:

類型 'DerivedClass' 與數據c ontract name'[some URI text]'不是 預計。考慮使用DataContractResolver或將靜態已知的任何類型 添加到已知類型的列表中 - 例如,使用KnownTypeAttribute屬性的 或將它們添加到傳遞給DataContractSerializer的已知類型的列表 。

我試圖將這些屬性添加到我的班在各種組合,但仍沒有運氣:

[Serializable] 
[KnownType(typeof(List<BaseClass>))] 
[XmlInclude(typeof(List<BaseClass>))] 
[KnownType(typeof(BaseClass))] 
[XmlInclude(typeof(BaseClass))] 
public class DerivedClass : List<BaseClass> 
{ 
    /// ... 
} 

PS- Sheehs,我是說認爲輸入字段都在這個網站時髦的唯一一個?當我試圖格式化時,事情會不斷移動...:|無論我是否想要按照自己的意願輸入文字,這都是一個偉大的網站。

回答

4

你必須一個ServiceKnownTypeAttribute爲您服務接口:

[ServiceKnownType(typeof(DerivedClass))] 
public interface IService 
{ 
    // Service declaration 
} 
+1

不確定這是否是最好的方法,因爲這會將客戶端代碼緊密地耦合到服務接口。該服務只知道List ,並不認爲它應該關心客戶端如何發送它。假設另一個客戶端想要派生DerivedClass,那麼服務器需要添加另一個屬性。不要認爲這對軟件維護非常有用。所有派生類的功能都與列表的包裝類似,因此它可以操縱使用操作符/方法中構建的泛型List <>的列表元素。 –

+0

當您無法控制服務代碼時,這是一個值得關注的問題。 –

0

有到register known types幾種方法。但首先請研究有關DataContracts的articlestypes supported by the DataContractSerializer

請注意,您沒有在DerivedClassBaseClass上添加DataContract屬性。儘管標記爲Serializable屬性的類是有效的,並且可以在WSDL中公開,但DataContractAttibute具有專爲互操作性設計的序列化規則,並且它是WCF的首選序列化機制。

如果您決定將數據合同上註冊已知類型那麼這應該足夠:

[DataContract]  
public class DerivedClass : List<BaseClass> 
{ 
    /// ... 
} 

[DataContract] 
[KnownType(typeof(DerivedClass))] 
public clas BaseClass 
{ 
    //Add the DataMemberAttribute to the properties you want serialized. 
} 

如果你想在您添加的ServiceContractServiceKnownType屬性的服務合同級別註冊的已知類型。

+0

BaseClass的定義與您注意到的一樣。客戶端只需從該類中派生出來,以利用泛型List <>操作符/方法;如果客戶簡單地採用了一種方法而不是一種方法,那麼實施就會奏效;也就是說,如果客戶沒有從名單中派生出來,而是將其作爲財產。但是這看起來很笨重。 服務是否有必要了解List 的派生實現?似乎沒有,客戶需要發送清單;客戶端派生的clss應該隱藏在服務器上 –

+0

您不必在服務合同和數據合同級別添加它。一個就足夠了。另一種方法是使用配置文件或使用KnownTypeAttbibute .ctor,該參數以參數形式返回IEnumerable已知類型的幫助程序方法的名稱。無論如何,我看不到你的派生類的重點。它讓你的設計更難理解,沒有任何好處(可以從你的例子和評論中看到)。刪除派生類並在服務操作中使用IList 或IEnumerable 。這樣你就可以封裝集合類型並擁有簡單的可維護代碼。 –

+0

派生類純粹是在列表上運行,就是這樣。只是幫手功能。就像在列表上運行的函數一樣;例如,將列表的所有項目屬性設置爲給定某些條件的值,並根據列表計算一些值。基本上,所有的數據和操作都包含在DerivedClass中,而不是每次我們需要執行常見任務時都需要創建一個單獨的「Helper」類。現在如果你說有兩個類(Derived和Helper)是一個好設計,我不同意。 –