【问题标题】:XML serialization of a nested object, but at the root level嵌套对象的 XML 序列化,但在根级别
【发布时间】:2012-01-24 15:44:56
【问题描述】:

我想序列化一个嵌套对象,使其属性与父对象处于同一级别(即不在嵌套标记中)。具体来说:我有一个 C# 对象:

[XmlRoot(ElementName="Root")]
public class TopLevel
{
   public string topLevelProperty;
   public NestedObject nestedObj;
}

public class NestedObject
{
   string propetyOnNestedObject;
}

我想要这样的 XML:

<root>
   <topLevelProperty>...</topLevelProperty>
   <propertyOnNestedObject>...</propertyOnNestedObject>
   <!--NOTE: propertyOnNestedObject would normally be inside a "<nested>" tag
       but I'm trying to avoid that here-->
</root> 

这可能吗?

【问题讨论】:

    标签: c# xml serialization


    【解决方案1】:

    您需要实现IXmlSerializable 接口来覆盖默认行为

    [XmlRoot(ElementName = "Root")]
    public class TopLevel : IXmlSerializable
    {
        public string topLevelProperty;
        public NestedObject nestedObj;
    
        public XmlSchema GetSchema()
        {
            return null;
        }
    
        public void ReadXml(XmlReader reader)
        {
            //...
        }
    
        public void WriteXml(XmlWriter writer)
        {
            writer.WriteElementString("topLevelProperty", topLevelProperty);
            writer.WriteElementString("propertyOnNestedObject", nestedObj.propetyOnNestedObject);
        }
    }
    

    CodeProject 上也有一篇关于如何正确实现接口的好帖子:http://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly

    【讨论】:

      【解决方案2】:

      作为一种情况,您可以公开嵌套的属性访问器,但这会使 TopLevel 对象稍微复杂一些。因此,作为一个案例,您可以引入一个单独的可序列化包装器,以将这种特殊情况的包装器与业务对象本身分离。

      [XmlRoot(ElementName="Root")] 
      public class TopLevel 
      {    
         public string topLevelProperty;    
      
         [XmlIgnore]
         public NestedObject nestedObj; 
      
         [XmlElement("NestedProperty")]
         public string NestedPropertyAccessor
         {
             get
             {
               return nestedObj.NestedProperty;
             }
             // set
         }
      } 
      

      如果您需要将可序列化对象与业务模型分离,则将其分开,这样您就不需要通过专门公开的属性来使业务对象本身复杂化以适应序列化格式:

      public class TopLevelSerializableWrapper
      {
          public TopLevelSerializableWrapper(TopLevel businessObject)
          {
          }
      
          // TODO: expose all proeprties which need to serialized
      }
      

      【讨论】:

        【解决方案3】:

        您可以使用YAXLib XML 序列化库轻松做到这一点:

        //[XmlRoot(ElementName = "Root")]
        [YAXSerializeAs("Root")]
        public class TopLevel
        {
            public string topLevelProperty { get; set; }
            public NestedObject nestedObj { get; set; }
        }
        
        public class NestedObject
        {
            [YAXElementFor("..")]
            string propetyOnNestedObject { get; set; }
        }
        

        注意YAXElementFor("..") 属性如何将序列化位置指向父元素。 (".." 看起来像文件系统路径中的父文件夹)。

        【讨论】:

          猜你喜欢
          • 2021-12-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-01-11
          • 2011-10-03
          • 2016-06-13
          • 2023-04-03
          • 2010-09-21
          相关资源
          最近更新 更多