嵌套对象的XML序列化,但在根级别

时间:2012-01-24 15:44:56

标签: c# xml serialization

我想序列化一个嵌套对象,使其属性与父对象处于同一级别(即,不在嵌套标记中)。具体来说:我有一个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> 

这可能吗?

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

作为一种情况,您可以公开嵌套的proeprty访问器,但这会使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
}

答案 2 :(得分:1)

您可以轻松地使用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("..")属性如何将序列化的位置指向父元素。 (".."看起来像文件系统路径中的父文件夹。)