2012-03-20 22 views
1

嘗試序列化類似聯合的數據類型。有一個枚舉字段,指示聯合中存儲的數據類型以及各種可能的字段類型。如何根據WCF中的內容自定義數據序列化?

想要的結果是DataContractSerializer產生的XML只包含枚舉和相關的字段。

可能的解決方案,其中沒有一個已經嘗試呢,主要有:

  • 使用自定義序列化和標記與自定義屬性,類似於this question工會性質。自定義序列化器會去除不需要的成員。
  • 使用ISerializationSurrogate並序列化一個包含相關數據的不同對象。
  • 不要在聯合中使用單獨的字段,請使用一個對象字段(這可以用作ISerializationSurrogate方法實施的一部分)。
  • 其他...?

例如:

[DataContract] 
public class WCFTestUnion 
{ 
    public enum EUnionType 
    { 
     [EnumMember] 
     Bool, 
     [EnumMember] 
     String, 
     [EnumMember] 
     Dictionary, 
     [EnumMember] 
     Invalid 
    }; 

    EUnionType unionType = EUnionType.Invalid; 

    bool boolValue = true; 
    string stringValue = "Hello"; 
    IDictionary<object, object> dictionaryValue = null; 

    // Could use custom attribute here ? 
    [DataMember] 
    public bool BoolValue 
    { 
     get { return this.boolValue; } 
     set { this.boolValue = value; } 
    } 

    // Could use custom attribute here ? 
    [DataMember] 
    public string StringValue 
    { 
     get { return this.stringValue; } 
     set { this.stringValue = value; } 
    } 

    // Could use custom attribute here ? 
    [DataMember] 
    public IDictionary<object, object> DictionaryValue 
    { 
     get { return this.dictionaryValue; } 
     set { this.dictionaryValue = value; } 
    } 

    [DataMember] 
    public EUnionType UnionType 
    { 
     get { return this.unionType; } 
     set { this.unionType = value; } 
    } 
} // Ends class WCFTestUnion 

測試

class TestSerializeUnion 
    { 
     internal static void Test() 
     { 
      Console.WriteLine("===TestSerializeUnion.Test()==="); 

      WCFTestUnion u = new WCFTestUnion(); 
      u.UnionType = WCFTestUnion.EUnionType.Dictionary; 
      u.DictionaryValue = new Dictionary<object, object>(); 
      u.DictionaryValue[1] = "one"; 
      u.DictionaryValue["two"] = 2; 

      System.Runtime.Serialization.DataContractSerializer serialize = new System.Runtime.Serialization.DataContractSerializer(typeof(WCFTestUnion)); 
      System.IO.Stream stream = new System.IO.MemoryStream(); 

      serialize.WriteObject(stream, u); 

      stream.Seek(0, System.IO.SeekOrigin.Begin); 
      byte[] buffer = new byte[stream.Length]; 
      int length = checked((int)stream.Length); 
      int read = stream.Read(buffer, 0, length); 
      while (read < stream.Length) 
      { 
       read += stream.Read(buffer, 0, length - read); 
      } 

      string xml = Encoding.Default.GetString(buffer); 

      System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); 
      doc.LoadXml(xml); 

      System.Xml.XmlTextWriter xmlwriter = new System.Xml.XmlTextWriter(Console.Out); 
      xmlwriter.Formatting = System.Xml.Formatting.Indented; 

      doc.WriteContentTo(xmlwriter); 
      xmlwriter.Flush(); 

      Console.WriteLine(); 
     } 
    } // Ends class TestSerializeUnion 

輸出:

<WCFTestUnion xmlns="http://schemas.datacontract.org/2004/07/WCFTestServiceContracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
    <BoolValue>true</BoolValue> 
    <DictionaryValue xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"> 
    <a:KeyValueOfanyTypeanyType> 
     <a:Key i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">1</a:Key> 
     <a:Value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">one</a:Value> 
    </a:KeyValueOfanyTypeanyType> 
    <a:KeyValueOfanyTypeanyType> 
     <a:Key i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">two</a:Key> 
     <a:Value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">2</a:Value> 
    </a:KeyValueOfanyTypeanyType> 
    </DictionaryValue> 
    <StringValue>Hello </StringValue> 
    <UnionType>Dictionary</UnionType> 
</WCFTestUnion> 

所需的輸出(僅使用場被串行化,用枚舉一起):

<WCFTestUnion xmlns="http://schemas.datacontract.org/2004/07/WCFTestServiceContracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 
    <DictionaryValue xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"> 
    <a:KeyValueOfanyTypeanyType> 
     <a:Key i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">1</a:Key> 
     <a:Value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">one</a:Value> 
    </a:KeyValueOfanyTypeanyType> 
    <a:KeyValueOfanyTypeanyType> 
     <a:Key i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">two</a:Key> 
     <a:Value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">2</a:Value> 
    </a:KeyValueOfanyTypeanyType> 
    </DictionaryValue> 
    <UnionType>Dictionary</UnionType> 
</WCFTestUnion> 

回答

2

這裏有幾個選項。你使用什麼取決於這個場景的複雜性(你還需要做些什麼,你需要多長時間以及以什麼方式來序列化這些數據,性能等)。看看這些選項,問問你是否有更多的問題,但大多數情況下,我建議你在選擇一個或混合解決方案之前,先從下面的列表中嘗試多種策略。

  • Use a data contract resolver。提供了一種在序列化和反序列化過程中動態地映射類型與線序表示之間的類型的機制,使您能夠靈活地支持遠遠超過您的開箱即用類型。

  • Use IObjectReference。您可以擁有一個類,該類在反序列化後實現並返回對其他對象的引用。

  • Use a data contract surrogate。這與您所指代的序列化代理不同,但也相似。我認爲這些可能會很好地爲你工作

+0

我已經與數據合同代理商一起,他們已經非常乾淨地工作。忘了回來這個問題,但。 已經看過解析器,但並不認爲這是正確的路要走。沒有看到IObjectReference,所以非常感謝。 – WaffleSouffle 2012-05-01 13:34:34

相關問題