2010-07-22 42 views
0

我在寫一個.net WCF服務。我已經寫了一些我想返回到WCF服務的調用代碼的類;因此,我用DataContract屬性來裝飾它們。如何在WCF客戶端中用DataContractAttribute裝飾的類中使用方法?

我們假設我的WCF服務叫做FooService。它包含一個名爲FooMethod方法,它返回FooData類型(其被飾以DataContract屬性的對象。假設FooData包含號碼列表和被叫FooAverage方法,它返回數的平均值。

在Visual Studio,我創建了一個新的應用程序來使用服務,我在我的WCF服務中添加了一個新的「服務引用」,並給它命名空間myWcfService在我的客戶端代碼中,我實例化一個代理類並獲得服務的連接。從我的代理獲取FooData對象,方法調用爲myWcfService.FooMethod()。它返回一個類型爲myWcfService.FooData的對象,該對象是根據FooService元數據確定的類型。

既然我有我的對象myWcfService.FooData類型,我怎樣才能將這些數據轉換成類型爲FooData的對象作爲服務代碼中的原始類型,以便我可以調用FooData.FooAverage()

編輯:我完全意識到數據以XML格式出現在管道中,並且該服務沒有返回裝飾有DataContract的類中的方法的邏輯;它不是可序列化的。我問的是:如果我可以引用包含服務中使用的DataContract類的類,是否有一種簡單的方法將數據反序列化到序列化的類中?

我願意接受現在的.net框架無法做到的答案。

回答

2

如果類型包含在項目中,WCF將允許類型重新使用。如果您的數據類型在某個Common項目中,那麼這些類型將被重新序列化(只要它們具有默認構造函數並標記爲序列化)。

雖然這只是你問題的一半。如果你想讓你的數據類型代理服務器的方法調用實現,那麼你可能需要Remoting(http://msdn.microsoft.com/en-us/library/ms973857.aspx)並使用Proxy對象。

+0

我會避免遠程處理 - WCF使這一過時。將操作添加到服務合約是在WCF中執行此操作的方法。但是,當我讀到這個問題時,這並不是他所問的。 – 2010-12-17 00:28:20

0

你不能。

你需要保持兩件事情完全分開:

  • 你有服務合同其定義這些方法可能需要類類型的方法(飾[OperationContract]屬性)

  • ,您使用[DataContract]屬性定義的參數

WCF的本質是將從客戶端到服務器的參數和類型串行化爲XML表示 - 因此,您可以通過數據協定的形式跨網線發送的數據是原始數據 - 無行爲 - 您無法通過DataContract類發送並調用一個方法。

在正常的設置中,您的客戶端數據類與它們在服務器端的類型不同 - 它們只是看起來的XML序列化格式相同。他們共享的就是他們的XML序列化 - 即獲得序列化的數據元素,僅此而已。 WCF是而不是某些遠程過程調用方法 - 它發送客戶端和服務器之間的數據專用消息(這是一個好東西!(tm))。

如果您需要能夠調用方法,請將該方法添加到您的服務合同中,作爲使用[OperationContract]屬性修飾的方法。

+0

-1當然,如果他想(如Nat Zauggs的答案所解釋的那樣)在客戶端使用他的原始(服務端定義的)FooData類型,並且調用它的方法。這個問題清楚地表明,他詢問了一種在對象的可序列化狀態上運行的方法:由於狀態在服務中被序列化並被反序列化回到客戶端的對象中,所以該方法將在客戶端上正常工作在服務器上。當然,如果一個方法依賴於私有的不可序列化狀態,那麼同樣不適用。 – 2010-12-17 00:22:06

+0

@克里斯Dickson:這將是非常灰心和非常糟糕的做法 - 我會說:只是**永遠不要**做到這一點! – 2010-12-17 06:05:57

+0

提問者問是否有可能。它是。至於這是否是好的做法:我同意你的看法,即在客戶和服務不一起開發(和版本化)的任何用法中,在它們之間共享類型是一個糟糕的主意。但是,WCF不僅僅是爲了SOA而設計的,而且也是爲了取代現有的IPC和進程內通信機制(比如Remoting),在某些情況下,這將是一個完全合理的設計決策。 – 2010-12-17 15:36:35

0

您可以在客戶端與部分類定義擴展myWcfService.FooData和定義FooAverage(),如果原始FooAverage()不具有此禁止任何依賴:

partial class FooData 
{ 
    public double FooAverage() { return Math.Average(Numbers); } 
} 

但請記住, FooData是數據傳輸對象,因此沒有任何私有狀態,這意味着你可以把所有的數據到非成員函數反正:

double average = Math.Average(foodata.Numbers);