简体   繁体   English

无法将派生类序列化为XML

[英]Unable to serialize a derived class to XML

I am trying to serialize following class hierarchy: 我正在尝试序列化以下类层次结构:

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 ;
            }
        }
    }

As you can see I am including the base class but still its throwing following exception: 如您所见,我包含了基类,但仍然引发以下异常:

The type TextProperties was not expected. 不应使用TextProperties类型。 Use the XmlInclude or SoapInclude attribute to specify types that are not known statically. 使用XmlInclude或SoapInclude属性可以指定静态未知的类型。

I´m not sure that the problem is really your class hierarchy itself, it seems to be okay. 我不确定问题确实出在您的类层次结构本身上,这似乎还可以。 You dont need to add the attribute. 您不需要添加属性。

Instead, you are likely trying to read/write an object of type TextProperties with an XmlSerializer created for objects of type Control. 相反,您可能尝试使用为控件类型创建的XmlSerializer读取/写入TextProperties类型的对象。 That won´t work, you need to use the serializer created specific to the type to serialize / deserialize. 那行不通,您需要使用针对该类型创建的序列化器来进行序列化/反序列化。

If this is not known at compile time, try to create a wrapping class that implements IXMLSerializable. 如果在编译时未知,请尝试创建实现IXMLSerializable的包装类。 When reading, this class must first read data to define the class of the wrapped object (a node attribute named "TypeName", for example). 读取时,此类必须首先读取数据以定义包装对象的类(例如,名为“ TypeName”的节点属性)。 It must then create the specific serializer for the given type at runtime and use it to load the wrapped object. 然后,它必须在运行时为给定类型创建特定的序列化器,并使用它加载包装的对象。

EDIT: Here is some sample code how it could be done. 编辑:这是一些示例代码,如何完成。 You will need to implement GetTypeByName yourself (eg. crawling through all loaded assemblies or just "hardwiring" some strings to a specific type you expect). 您将需要自己实现GetTypeByName(例如,爬网所有已加载的程序集,或仅将某些字符串“硬接线”为所需的特定类型)。 The code should suffice to be integrated into a class with a property "WrappedObject". 该代码应足以集成到具有“ 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);        
  }

I think you need to put attribute above the parent class like this 我认为您需要像这样将属性放在父类之上

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

in child class you put 在儿童班上

[Serializable]
   public class ChildClass: ParentClass
    {   
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM