序列化类,“移动”属性到其他元素

时间:2012-01-23 03:51:37

标签: c# .net xml-serialization

我正在尝试控制在序列化类时呈现类属性的位置:我需要将属性显示为特定元素的属性:

namespace ConsoleApplication6
{
    public class Program
    {
        static void Main(string[] args)
        {
            var myClass = new MyClass();
            myClass.MyList.Add(new Item() { ID = 1 });
            myClass.MyList.Add(new Item() { ID = 2 });
            myClass.Xxx = "Hello World!";

            var sx = new XmlSerializer(myClass.GetType());
            sx.Serialize(Console.Out, myClass);
        }

        public class MyClass
        {
            public MyClass()
            {
                MyList = new List<Item>();
            }

            public List<Item> MyList { get; set; }

            [XmlAttributeAttribute(AttributeName = "x")]
            public string Xxx { get; set; }
        }

        public class Item
        {
            public int ID { get; set; }
        }
    }
}

这很好地序列化了这个:

<?xml version="1.0" encoding="ibm850"?>
<MyClass xmlns:xsi=" ... " xmlns:xsd=" ... " x="Hello World!">
  <MyList>
    <Item>
      <ID>1</ID>
    </Item>
    <Item>
      <ID>2</ID>
    </Item>
  </MyList>
</MyClass>

但是:我的问题是,我需要将属性Xxx呈现为<MyList>元素的属性,而不是<MyClass>根元素,如下所示:

...
<MyList x="Hello World!">
...

我认为应该可以使用类/属性上的XmlSerialization属性,但我无法弄明白。我甚至尝试创建List的子类,将属性Xxx添加到其中,但.NET XML序列化忽略了额外的属性,XML输出就像List&lt; ..&gt;通常是序列化的。

更新:以下是我尝试创建“自定义列表”的代码,该代码继承自List<Item>并添加了额外的属性:

public class Program
{
    static void Main(string[] args)
    {
        var myClass = new MyClass();
        myClass.MyList.Add(new Item() { ID = 1 });
        myClass.MyList.Add(new Item() { ID = 2 });
        myClass.MyList.Xxx = "Hello World!";

        var sx = new XmlSerializer(myClass.GetType());
        sx.Serialize(Console.Out, myClass);
    }

    public class MyClass
    {
        public MyClass()
        {
            MyList = new CustomList();
        }

        public CustomList MyList { get; set; }
    }

    public class Item
    {
        public int ID { get; set; }
    }

    public class CustomList : List<Item>
    {
        [XmlAttributeAttribute(AttributeName = "x")]
        public string Xxx { get; set; }
    }
}

输出xml如下所示:

<?xml version="1.0" encoding="ibm850"?>
<MyClass xmlns:xsi=" ... " xmlns:xsd=" ... ">
  <MyList>
    <Item>
      <ID>1</ID>
    </Item>
    <Item>
      <ID>2</ID>
    </Item>
  </MyList>
</MyClass>

注意Xxx属性是如何在xml ...

中表示的

3 个答案:

答案 0 :(得分:1)

我认为对于该级别的控制,您需要使用IXmlSerializable界面。我不认为使用属性可以在这里工作。

答案 1 :(得分:0)

根据this MSDN discussion

  

如果是集合,XmlSerializer不会序列化任何成员。只要   集合项目被序列化。这是设计,基本上是一个   决定将集合作为数组处理而不是作为类   多个属性,因此集合应该看起来像数组   电线,因此他们没有任何其他成员收集   通过将[XmlElement]添加到成员中,可以“展平”项目   ICollection类型。

所以你所描述的缺陷显然是设计的。除非您决定通过某些转换运行生成的XML,否则我不确定您打算如何使用XML序列化属性来实现它。

答案 2 :(得分:0)

这篇文章提供了一些额外的信息,包括一些选项: When a class is inherited from List<>, XmlSerializer doesn't serialize other attributes

要点:

  • IXmlSerializable(如Kai所述)
  • 的DataContractSerializer
  • 创建一个新类,其中X(您的属性)是一个属性,并提供一个列表的附加属性(因此,不要创建包装类,而不是子类化列表)。例如:

    public class MyListWrapper<T> 
    {
       public MyListWrapper()
       {
          Data = new List<T>();
       }
    
       [XmlAttribute(AttributeName="x")]
       public string Xxx { get; set; }
    
       [XmlElement]
       public List<T> Data { get; set; }
    }
    

    请注意,这会将Items输出为“Data”元素。如果您愿意在Data上删除泛型类型参数并将其设为List(Item),那么您可以获取项目。

希望有所帮助!