【问题标题】:Unable to serialize a derived class to XML无法将派生类序列化为 XML
【发布时间】:2015-03-18 08:37:51
【问题描述】:

我正在尝试序列化以下类层次结构:

public class Control
    {
        public virtual string Name {get; set;}

        public virtual string Type {get; set;}

        public virtual string Text { get; set; }

        public virtual SerializableFont Font { get; set; }

        private Operation op = new Operation();
        public Operation Events { get { return op; } }
    }
[System.Xml.Serialization.XmlInclude(typeof(Control))]
    public class TextProperties : Control
    {
        public Label txt;

        public TextProperties()
        {
        }

        public override string Type
        {
            get { return "Text"; }
        }
        public override string Text
        {
            get { return txt.Text; }
            set
            {
                txt.Text = value;
            }
        }
        public override SerializableFont Font
        {
            get { return new SerializableFont(txt.Font); }
            set
            {
                txt.Font = new SerializableFont().Font ;
            }
        }
    }

如您所见,我包含了基类,但仍然抛出以下异常:

TextProperties 类型不是预期的。使用 XmlInclude 或 SoapInclude 属性来指定不属于 静态已知。

【问题讨论】:

    标签: c# .net xml xml-serialization


    【解决方案1】:

    我不确定问题真的出在你的类层次结构本身,它似乎没问题。您不需要添加属性。

    相反,您可能会尝试使用为 Control 类型的对象创建的 XmlSerializer 来读取/写入 TextProperties 类型的对象。这不起作用,您需要使用特定于类型创建的序列化程序来序列化/反序列化。

    如果在编译时不知道,请尝试创建一个实现 IXMLSerializable 的包装类。在读取的时候,这个类必须先读取数据来定义被包装对象的类(例如一个名为“TypeName”的节点属性)。然后它必须在运行时为给定类型创建特定的序列化程序并使用它来加载包装的对象。

    编辑:这是一些示例代码如何完成。您将需要自己实现 GetTypeByName(例如,爬取所有加载的程序集,或者只是将一些字符串“硬连线”到您期望的特定类型)。代码应该足以集成到具有“WrappedObject”属性的类中。

      public XmlSchema GetSchema()
      {
         return null;
      }
    
      public void ReadXml(XmlReader reader)
      {
         reader.MoveToContent();       
         var typeName = reader.GetAttribute("TypeName");
         reader.ReadStartElement();         
         var serializer = new XmlSerializer(GetTypeByName(typeName));
         WrappedObject = serializer.Deserialize(reader);
         reader.ReadEndElement();
      }
    
      public void WriteXml(XmlWriter writer)
      {         
         writer.WriteAttributeString("TypeName", "", GetTypeByName(WrappedObject));
    
         var serializer = new XmlSerializer(typeof(WrappedObject));
         serializer.Serialize(writer, WrappedObject);        
      }
    

    【讨论】:

    • 你能提供一个示例代码吗?我不知道怎么用IXMLSerializable
    • 完成。希望够了。
    【解决方案2】:

    我认为你需要像这样将属性放在父类之上

    [XmlInclude(typeof(ChildClass))] 
    [Serializable]
    public abstract class ParentClass
    {
        public abstract string Name { get; set; }
    }
    

    在你放置的子类中

    [Serializable]
       public class ChildClass: ParentClass
        {   
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多