2011-06-11 78 views
8

當我在客戶端上創建DataContract的實例時,我需要某些數據成員獲取一些值。這不是使用構造函數發生的。我搜索了不同的論壇,發現我們必須使用[OnDeserializing]和[OnDeserialized]屬性。這也不起作用。有人可以在這裏提出一些建議。另一種選擇是在客戶端的部分類中創建構造函數。我想避免這種情況。WCF DataContract中的構造函數未反映在客戶端上

請找到下面的代碼:

服務器端:Datacontract

[DataContract] 
public class Account 
{ 

    private int mAccountId; 
    private string mAccountName; 

    public Account() 
    { 
     mAccountId = 5; 
     mAccountName = "ABC"; 
    } 

    [OnDeserializing] 
    public void OnDeserializing(StreamingContext context) 
    { 
     mAccountId = 5; 
     mAccountName = "ABC"; 
    } 

    [OnDeserialized] 
    public void OnDeserialized(StreamingContext context) 
    { 

    } 

    [DataMember] 
    public int AccountId 
    { 
     get 
     { 
      return mAccountId; 
     } 
     set 
     { 
      mAccountId = value; 
     } 
    } 

    [DataMember] 
    public string AccountName 
    { 
     get 
     { 
      return mAccountName; 
     } 
     set 
     { 
      mAccountName = value; 
     } 
    } 


} 

客戶端 - 初始化

namespace TestClient 
{ 
    public partial class _Default : System.Web.UI.Page 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      Account acc = new Account(); 

     } 
    } 
} 
+0

WCF客戶端 - 服務器的連接** **只鏡像數據的合同數據方面 - ** **沒有任何代碼,你可能在你的數據類。畢竟:僅數據可以序列化成由XSD(XML模式)所示的格式,並通過線路發送 - 沒有代碼。 – 2011-06-11 19:15:22

回答

14

用於創建WCF代理類的代碼生成器創建兼容的合同類型,並沒有使用與W​​CF服務使用的完全相同的類型。達到你想要的最簡單的方法,就是你的客戶端上創建自己的構造函數,因爲生成的代碼是partial

partial class Account 
{ 
    public Account() 
    { 
     AcountId = 5; 
     AccountName = "ABC"; 
    } 
} 

如果你不想這樣做,你可以得到WCF重用類型已被您的客戶項目引用。因此,如果數據約定類位於單獨的庫中(如建議的那樣),則可以引用該庫,然後重新配置WCF客戶端項目以重用引用程序集中的共享類型。

+0

任何其他解決方法?爲什麼[OnDeserializing]/[OnDeserialized]屬性不工作.....謝謝... – Subhasis 2011-06-11 13:32:17

+0

因爲這些屬性是反序列化=當您從服務而不是當你調用構造函數得到'Account'! – 2011-06-11 13:42:18

+2

+1將數據合同類放入另一個庫中。我們已經把它們放在與服務接口定義庫,並在現實中交流的合同是服務的關注,而不是域模型的關注。 – 2011-06-11 14:01:29

13

歸因於DataMember屬性的屬性僅定義了將包含在生成的WSDL/XSD中的內容。客戶端將根據wsdl/xsd生成自己的類用於與服務進行通信。它不使用在服​​務器上使用的相同的類。

這就是爲什麼你不會得到:

  • DataContract類定義的任何構造
  • 任何私人[DataMember]性能/場(客戶端總是會產生公共屬性/字段)
  • 任何行爲定義在DataContract類中

想象一下,java客戶端想要連接到您的服務的場景。你期望用相同的構造函數生成java類嗎?那麼[OnDeserialized]屬性呢?怎麼樣一個Java腳本客戶端,或Python客戶端?

當你開始以這種方式思考它的時候,你開始明白爲什麼你不能擁有你想要的東西(至少不是沒有在客戶端和服務器之間共享庫)。

實際情況是,您不能強制客戶端擁有始終具有默認值的類,並且客戶端無法始終發送有效數據,但客戶端始終可以發送包含垃圾的消息(如果需要)。您可以使用IsRequired和'EmitDefaultValue`來控制消息的某些方面,它會將檢查添加到xsd中以確保消息中存在某些內容,但您必須在服務器上進行驗證,但不能假定你得到的對象將被驗證。

我的建議是從你的域對象創建DTO的跨線,其中不包含任何形式的檢查派,他們只是簡單的袋保存數據。然後創建工廠以將您的域對象轉換爲DTO和DTO到客戶端對象中。工廠只需要DTO並將成員傳遞給域對象的構造函數。那麼你的驗證邏輯可以存在於它所屬的域對象的構造函數中。有了方法,你現在有你最終可能會稍微扭所以它可以從兩個構造,並在[OnDeserialized]的方法來進行驗證。