簡體   English   中英

XML被反序列化為基類而不是派生類

[英]Xml being deserialized into base class instead of derived classes

我知道這是一個熱門話題,我進行了廣泛的研究,但沒有找到解決問題的答案。

我有一個基類IntroductionAction和2個派生類IntroductionActionComplexIntroductionActionSimple 我有一個IntroductionAction對象的列表,向其中添加了兩種派生類型的對象。 我的課程如下:

[XmlInclude(typeof(IntroductionActionComplex))]
[XmlInclude(typeof(IntroductionActionSimple))]
public class IntroductionAction
{
    public IntroductionAction() { }
}

public class IntroductionActionComplex : IntroductionAction
{
    [XmlIgnore]
    public string name { get; set; }

    [XmlElement(ElementName = "QuestionString")]
    public string question { get; set; }

    [XmlElement(ElementName = "AnswerString")]
    public List<string> answerStrings { get; set; }

    public IntroductionActionComplex()
    {
        name = string.Empty;
        question = null;
        answerStrings = new List<string>();
    }
}

public class IntroductionActionSimple : IntroductionAction
{
    [XmlIgnore]
    public string name { get; set; }

    [XmlText]
    public string Value { get; set; }

    public IntroductionActionSimple()
    {
        Value = string.Empty;
    }
}

然后,我如下創建列表

[XmlElement("IntroductionAction")]
public List<IntroductionAction> introductionActions { get; set; }

我正在使用XmlSerializer ,一切都正確序列化。 這是包含正確的每個派生類之一的列表的結果XML。

<IntroductionAction>
  <QuestionString>
    test
  </QuestionString>
  <AnswerString>
    test
  </AnswerString>
  <AnswerString>
    test
  </AnswerString>
</IntroductionAction>
<IntroductionAction>
  test
</IntroductionAction>

此XML文件將進入一個設備,該設備不會將其讀取為XML,而只是搜索標簽並完成其所需的任何工作,因此該文件不能包含任何XSI或XSD標簽,縮進等通常與正確的XML相關聯。

我的反序列化代碼很簡單:

public static T Deserialize_xml_Config<T>(string file1, T obj)
{
   XmlSerializer deserializer = new XmlSerializer(obj.GetType());
   using (TextReader reader = new StreamReader(file1))
   {
      return (T)deserializer.Deserialize(reader);
   }
}

最后是我的問題。 當我反序列化時,它將反序列化為基類IntroductionAction而不是衍生類。 這些IntroductionAction類只是我正在序列化/反序列化的一個更大對象的一部分。 我嘗試使基類抽象,因為它不包含任何功能,但是在反序列化時出現錯誤,提示

指定的類型是抽象的:name ='IntroductionAction'

盡管我的XmlIncludes似乎無法找到派生類。

我嘗試將類型添加到序列化器中,但是沒有用。

任何幫助深表感謝。

編輯:這是通過將類型添加到序列化程序的意思

XmlSerializer deserializer = new XmlSerializer(obj.GetType(), new Type [] { typeof(IntroductionActionComplex), typeof(IntroductionActionSimple) });
using (TextReader reader = new StreamReader(file1))
{
   return (T)deserializer.Deserialize(reader);
}

我也嘗試使用XmlAttributeOverrides

XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
var attrs = new XmlAttributes();
XmlElementAttribute attr = new XmlElementAttribute();
attr.ElementName = "IntroductionAction";
attr.Type = typeof(IntroductionActionComplex);
attrs.XmlElements.Add(attr);
attr.ElementName = "IntroductionAction";
attr.Type = typeof(IntroductionActionSimple);
attrs.XmlElements.Add(attr);
attrOverrides.Add(typeof(IntroductionAction), "IntroductionAction", attrs);

XmlSerializer deserializer = new XmlSerializer(obj.GetType(), attrOverrides);
using (TextReader reader = new StreamReader(file1))
{
   return (T)deserializer.Deserialize(reader);
}

我覺得你很親密。 下面是基於派生類類型保存和加載XML文件的完整示例。 這會將節點保存為派生類型本身,因此重新加載將保留所需的類型,而不是轉換回基本類型。 您可能需要添加異常處理,這只是一個快速的解決方案。 我沒有更改您的基本IntroductionAction或派生的IntroductionActionComplex / IntroductionActionSimple類。

public class RootNode
{
   [XmlElement("IntroductionAction")]
   public List<IntroductionAction> introductionActions { get; set; }

   public RootNode()
   {
      introductionActions = new List<IntroductionAction>();
   }

   private static XmlAttributeOverrides GetXmlAttributeOverrides()
   {
      XmlAttributeOverrides xml_attr_overrides = new XmlAttributeOverrides();
      XmlAttributes xml_attrs = new XmlAttributes();
      xml_attrs.XmlElements.Add(new XmlElementAttribute(typeof(IntroductionActionComplex)));
      xml_attrs.XmlElements.Add(new XmlElementAttribute(typeof(IntroductionActionSimple)));
      xml_attr_overrides.Add(typeof(RootNode), "introductionActions", xml_attrs);
      return xml_attr_overrides;
   }

   // Add exception handling
   public static void SaveToFile(RootNode rootNode, string fileName)
   {
      using (MemoryStream mem_stream = new MemoryStream())
      {
         XmlSerializer serializer = new XmlSerializer(rootNode.GetType(), RootNode.GetXmlAttributeOverrides());
         serializer.Serialize(mem_stream, rootNode);

         using (BinaryWriter output = new BinaryWriter(new FileStream(fileName, FileMode.Create)))
         {
            output.Write(mem_stream.ToArray());
         }
      }
   }

   // Add exception handling
   public static RootNode LoadFromFile(string fileName)
   {
      if (File.Exists(fileName))
      {
         using (FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
         {
            using (TextReader reader = new StreamReader(file))
            {
               XmlSerializer serializer = new XmlSerializer(typeof(RootNode), RootNode.GetXmlAttributeOverrides());
               return (RootNode)serializer.Deserialize(reader);
            }
         }
      }
      return null;
   }
}

測試程序:

internal class Program
{
   private static void Main(string[] args)
   {
      RootNode obj = new RootNode();
      obj.introductionActions.Add(new IntroductionActionComplex() { question = "qTest", answerStrings = { "aTest1", "aTest2" }, name = "aName1" });
      obj.introductionActions.Add(new IntroductionActionSimple() { name = "aName2", Value = "aValue" });

      RootNode.SaveToFile(obj, "Test.xml");

      RootNode obj2 = RootNode.LoadFromFile("Test.xml");
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM