【问题标题】:Serializing a List hold an interface to XML序列化 List 持有 XML 的接口
【发布时间】:2009-07-15 14:18:45
【问题描述】:

我一直在阅读,但我没有找到解决问题的方法

我目前正在使用一个包含我所有数据的业务对象,我们需要将此对象与 XML 相互转换。

我的对象包含一个动作列表(列表...),但有 2 种动作类型(目前)。 我必须操作类型 SimpleAction 和 CompositeAction,它们都从 IAction 继承,允许它们都保存在 Actions 列表中。

现在您可能会看到问题,因为接口无法序列化,因为它们没有数据。

如何使用一些示例代码编写一个获取该对象类型并执行然后序列化具有正确类型的对象的类或序列化程序?

一些代码:

  [XmlArray("Actions")]
  public List<IAction> Actions { get; set; }

  public interface IAction
   {
     int ID { get; set; }

     ParameterCollection Parameters { get; set; }

     List<SectionEntity> Validation { get; set; }

     TestResultEntity Result { get; set; }

     string Exception { get; set; }
   }

[XmlType("A")]
public class SimpleActionEntity : IAction
{
    #region IAction Members

    [XmlAttribute("ID")]
    public int ID { get; set; }

    [XmlIgnore]
    public ParameterCollection Parameters { get; set; }

    [XmlIgnore]
    public List<SectionEntity> Validation { get; set; }

    [XmlIgnore]
    public TestResultEntity Result { get; set; }

    [XmlElement("Exception")]
    public string Exception { get; set; }

    #endregion
}

任何帮助将不胜感激。 :)

【问题讨论】:

    标签: c# xml serialization


    【解决方案1】:

    您可以使用 XmlArrayItemAttribute,正如我们所讨论的,创建 IAction 列表并不好,所以创建基类很好

    public interface IAction {}
    public abstract class ActionBase : IAction {}
    public class SimpleAction : ActionBase {}
    public class ComplexAction : ActionBase {}
    
    
    [XmlArray("Actions")]
    [XmlArrayItem(typeof(SimpleAction)),XmlArrayItem(typeof(ComplexAction))]
    public List<ActionBase> Actions { get; set; }
    

    其实你也可以像这样控制 xml 文件中的元素名称:

      [XmlArray("Actions")]
      [XmlArrayItem(typeof(SimpleAction),ElementName = "A")]
      [XmlArrayItem(typeof(ComplexAction),ElementName = "B")]
      public List<ActionBase> Actions { get; set; }
    

    【讨论】:

    • 当我设计对象结构时,我认为你可以这样做,但是当我尝试序列化时,我得到一个内部异常,说我无法序列化接口。
    • 您可以重新设计对象模型以使用实现接口IAction的抽象类,然后从抽象类继承所有Action类。
    • 这就是约翰在下面所说的
    • 我已经更新了我的答案以反映我们的讨论。在这种情况下,您需要 XmlArrayItem 属性来序列化 SimpleAction 和 ComplexAction 及其所有可序列化字段,而不仅仅是基类字段。
    【解决方案2】:

    好的,我已经创建了一个我觉得可以很好地完成我想要的解决方案。

    我所做的是而不是持有

     [XmlArray("Actions")]
     public List<IAction> Actions { get; set; }
    

    我决定创建一个处理列表的 ActionsCollection 类,但也允许我使用 IXMLSerializable 覆盖 ReadXml 和 WriteXML 方法,以便我可以处理列表的序列化和反序列化方式。

    [XmlElement("Actions")]
    public ActionCollection Actions { get; set; }
    
    public class ActionCollection: CollectionBase, IXmlSerializable
    {
        #region IList Members
          ...
        #endregion
    
        #region ICollection Members
         ...
        #endregion
    
        #region IEnumerable Members
        ...
        #endregion
    
        #region IXmlSerializable Members
    
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }
    
        public void ReadXml(System.Xml.XmlReader reader)
        {
           //TODO
        }
    
        public void WriteXml(System.Xml.XmlWriter writer)
        {
            foreach (IAction oAction in List)
            {       
                    XmlSerializer s = new XmlSerializer(oAction.GetType());
                    s.Serialize(writer, oAction);
            }
        }
    
        #endregion
    }
    

    【讨论】:

    • 好。我认为放置 [XmlInclude("SimpleAction")][XmlInclude("ComplexAction")] 也可以。
    【解决方案3】:

    也许如果您从实现接口的通用抽象基类派生两个动作类?

    public interface IAction {}
    public abstract class ActionBase : IAction {}
    public class SimpleAction : ActionBase {}
    public class ComplexAction : ActionBase {}
    

    那么不要使用List&lt;IAction&gt;,而是使用List&lt;ActionBase&gt;。

    【讨论】:

    • 我也试过这个,但也许我实现错了,因为当序列化程序到列表时它只序列化基类并且这种行为没有用,因为 ComplexAction 中有许多附加属性
    • 如果SimpleAction 继承自另一个基类呢?并且不能从另一个基类继承。
    猜你喜欢
    • 2012-02-27
    • 1970-01-01
    • 2010-11-17
    • 1970-01-01
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多