2012-07-12 15 views
1

我在將類序列化到XML時遇到問題。我創建了一個運行顯示錯誤的示例代碼。我想序列化名爲「ContentContainer」的類,ContentContainer有一個類型爲「ContentItemBase」的項目集合。因爲我的要求我執行這些類如下。但是如果實際序列化調用時代碼到達部分,則序列化器會拋出此異常:Xml序列化例外:不期望類型UserQuery + SpecificContentItem。使用XmlInclude或SoapInclude

不希望類型UserQuery + SpecificContentItem。使用 XmlInclude或SoapInclude屬性可以指定靜態爲非 的類型。

我已經搜索了這個問題,但我的要求我不能實現在異常消息中提到的XmlInclude方法。 有沒有解決方案(設計或實施提示)這個問題和類似的問題?

CODE:

void Main() 
{ 
    var item = new SpecificContentItem{ Name = "Test", Value = "TestValue" , SpecificField="TestField"}; 
    var container = new ContentContainer(); 
    container.Items.Add(item); 
    container.Name = "Test Container"; 
    XmlSerializer ser= new XmlSerializer(typeof(ContentContainer)); 
    StringWriter writer = new StringWriter(); 
    ser.Serialize(writer, container); 
    string result = writer.ToString(); 
} 
public abstract class ContentItemBase 
{ 
    public abstract string Name {get; set;} 
    public abstract string Value {get; set;} 
} 

public class SpecificContentItem: ContentItemBase 
{ 
    public string SpecificField {get; set;} 
    public override string Name {get; set;} 
    public override string Value {get; set;} 
} 
public class ContentContainer 
{ 
    public ContentContainer() 
    { 
     Items = new ContentItemCollection(); 
    } 
    public string Name {get;set;} 
    public ContentItemCollection Items{get; set;} 
} 

public class ContentItemCollection : IEnumerable<ContentItemBase> 
{ 
     public SpecificContentItem SpecificItem { get; set; } 
     public IEnumerator<ContentItemBase> GetEnumerator() 
     { 
      if (SpecificItem != null) 
       yield return SpecificItem; 
     } 
     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
     { 
      return GetEnumerator(); 
     } 
     public void Add(Object obj) 
     { 
      if (obj is SpecificContentItem) 
       SpecificItem = (SpecificContentItem)obj; 
     } 
} 
+0

呃。你不能使用XmlInclude的任何特定原因? – 2012-07-12 08:52:04

+0

但是,嘿,使用LINQPad嘗試你的代碼的榮譽。實際上,很少有人會費心製作片段,以便在諸如此類的工具中正確描述他們的問題。 – 2012-07-12 09:02:52

+0

謝謝!我試過「ContentContainer」類中的XmlInclude是否有任何方法在我的「ContentItemCollection」類中使用它? – 2012-07-12 09:36:00

回答

1

創建您的串行爲:

XmlSerializer ser = new XmlSerializer(typeof(ContentContainer), 
          new Type[] { typeof(SpecificContentItem) }); 

應該做的伎倆。

您還可以添加一個Serialize方法ContentContainer

public string Serialize() 
{ 
    var types = Items.Select(x => x.GetType()).Distinct().ToArray(); 
    XmlSerializer ser = new XmlSerializer(typeof(ContentContainer),types); 
    StringWriter writer = new StringWriter(); 
    ser.Serialize(writer, this); 
    return writer.ToString(); 
} 
+0

此解決方案是否打破了「本地結果」原則? 我的項目的序列化部分是在另一個DLL。 – 2012-07-12 09:06:13

+1

@ L.B。我真的建議你不要**使用這個'XmlSerializer'構造函數的重載,因爲它對內存中生成的序列化程序集程序使用NO緩存。因此,這會導致性能問題和看不見的內存使用問題,因爲它會在每次調用該構造函數時在**上創建一個新程序集。 – Aphelion 2012-07-12 09:28:12

+0

如果實例化的序列化程序本身被緩存了,不依賴於幕後裝配緩存的魔法麼? – 2012-07-12 09:36:00

0

由於允許使用XmlInclude似乎是模糊的,我還是要建議

[XmlInclude(typeof(SpecificContentItem))] 
public class ContentItemCollection : IEnumerable<ContentItemBase> 
{ 

一個可能的解決方案。如何適用於你的真實世界的情況有點難以分辨,但我希望它適用和有效!

+0

這不適用於我的真實情況。我不知道爲什麼這在linqpad版本的問題..:| – 2012-07-12 10:58:53

+1

然後,我同意前面的兩個答案,使用XmlSerializer的構造函數重載,該構造函數重載多個類型參數 - 如果要重用它,則手動緩存序列化程序。 – 2012-07-12 11:35:47