2014-01-13 31 views
8

我們有一個使用幾個DataContracts現有的WCF服務。我們要根據設備上修改的系列化,使從移動設備訪問時,服務應該序列只有一些重要的數據成員(不是全部)動態忽略獲取序列化的數據成員

我們有2個選擇這裏

  1. 創建獨立的操作和不同類型的設備 數據契約
  2. 惹實際XML序列化和抑制基於設備上創建 不必要的元素

我們不想與第一個選項一起使用,因爲它將來會引入大量冗餘代碼問題

小型研究表明我們需要使用IXmlSerializable並重寫readXML()和writeXML()方法。但在同一時間,我已經看到的地方,DataContract和IXmlSerializable的不應該在一起

的任何實例與實際系列化亂用是極大的讚賞。

[DataContract] 
public class TokenMessage 
{ 
    string tokenValue; 
    string extraValue; 
    [DataMember] 
    public string Token 
    { 
     get { return tokenValue; } 
     set { tokenValue = value; } 
    } 
    [DataMember] 
    public string Extra 
    { 
     get { return extraValue; } 
     set { extraValue = value; } 
    } 
} 

現在,當我訪問返回一個典型TokenMessage數據契約,來自移動設備的服務,我不希望「額外」數據成員被序列化,即當我提供一個不同的參數來操作合同時,應該能夠序列化的一些/所有的數據成員(取決於操作)

PS:現在請忽略設備檢測部分。讓我們假設我們在操作合同中有一個參數,它可以幫助我們識別設備

+0

使用接口並返回接口而不是類。 – Dalorzo

回答

-2

在您的模型中添加一個屬性'ShouldSerializeYOUR_PROPERTY_NAME',如果您不希望該屬性序列化,請將其設置爲false。 查看更多在這裏:http://msdn.microsoft.com/en-us/library/system.windows.dependencyobject.shouldserializeproperty(v=vs.110).aspx

+0

你的意思是說 - 「添加ShouldSerializeToken和ShouldSerializeExtra屬性,並將它們設置爲false?」 WCF會自動檢測到這? –

+0

上面的方法沒有運氣:( –

+2

'ShouldSerialize'涉及WPF,我不知道它將如何幫助您的WCF服務。 –

1

有一種方法,但我認爲這將需要生成額外DataContract但仍然沒有必要爲不同類型的設備進行單獨操作和數據的合同。 它能經典的實現運行時多態性。我在這裏只給想法:

假設你有一個通用的DataContract,如:

[DataContract] 
[KnownType(typeof(Extra))] 
[KnownType(typeof(Extra2))] 
public class TokenMessage 
{ 
    string tokenValue; 
    string extraValue; 
    [DataMember] 
    public string Token 
    { 
     get { return tokenValue; } 
     set { tokenValue = value; } 
    } 

} 

其他設備的具體合同可以繼承TokenMessage作爲基類,如:

[DataContract] 
public class Extra:TokenMessage 
{ 
    [DataMember] 
    public string Extra 
    { 
    get ;set; 
    } 
} 

[DataContract] 
public class Extra2:TokenMessage 
{ 
    [DataMember] 
    public string Extra2 
    { 
    get ;set; 
    } 
} 

現在在運行時間你說你知道的承包經營合同,這有助於我們識別設備的參數。說根據設備類型,你可以實例化基地類等衍生類:

TokenMessage tm= new Extra(); 

OR

TokenMessage tm= new Extra2(); 

所以在運行時,你將決定哪個設備合同將genric響應的一部分。

注意:添加KnownType將在wsdl中爲基類內的所有已知類型生成單獨的xsd,但在運行時保存數據的序列化,因爲這應該取決於所選的實際繼承。

3

我不相信@Pranav辛格的答案的一些變化是不是一個更好的設計,但是這不是你的問題......

正如你在.NET中的評論屬性可以提及的是通過靜態設計。這意味着動態添加/刪除[DataMember]不是一個好的選擇。有可能的。有像使用Reflection.Emit這樣的選項來重新創建具有元數據更改的實例(請參閱Can attributes be added dynamically in C#?的所有答案),但所有這些路由都很複雜。

我看到兩個合理的方案:

1)實現對服務IParameterInspector。在AfterCall()方法中,您可以在序列化之前檢查並更改返回給客戶端的參數。有一些工作使用反射來動態確定參數類型並設置它們的值,但它並不複雜。這是更好的設計,可以重用許多合同或服務中的行爲。 Carlos Figueira's blog是WCF擴展示例的最佳來源。

2)使用[OnSerializing][OnSerialized]事件。在[DataContract]中,您可以暫時更改序列化期間屬性返回的內容。 這些事件實際上是爲了啓用初始化而設計的,因此這種解決方案有點破解。此解決方案也不是線程安全的。但它確實將代碼包含在DataContract類中並快速解決了問題(我認爲您正在尋找快速)。

解決方案#2不妨看起來像:

[DataContract] 
public class TokenMessage 
{ 
    string tokenValue; 
    string extraValue; 

    bool enableExtraValue = true; 

    [DataMember] 
    public string Extra 
    { 
     get { 
       if (enableExtraValue) 
         return extraValue; 
       return null; 
      } 
     set { extraValue = value; } 
    } 

    [OnSerializing()] 
    internal void OnSerializingMethod(StreamingContext context) 
    { 
     enableExtraValue = false; 
    } 

    [OnSerialized()] 
    internal void OnSerializedMethod(StreamingContext context) 
    { 
     enableExtraValue = true; 
    } 
} 

解決方案#2是一個快速解決方案(這是我認爲你正在尋找)。

解決方案#1是更好的設計。