【问题标题】:How do I Set XmlArrayItem Element name for a List<Custom> implementation?如何为 List<Custom> 实现设置 XmlArrayItem 元素名称?
【发布时间】:2011-11-24 08:49:00
【问题描述】:

我想创建一个自定义的 XML 结构如下:

<Hotels>
    <Hotel />
</Hotels>

我已经创建了List 的实现,只是为了能够做到这一点。我的代码如下:

[XmlRootAttribute(ElementName="Hotels")]
public class HotelList: List<HotelBasic>

因为List持有的类不是Hotel而是HotelBasic我的xml是这样的

<Hotels>
   <HotelBasic />
</Hotels>

如何在无需实现 ISerializableIEnumerable 的情况下解决此问题?

【问题讨论】:

  • 你要序列化还是反序列化?

标签: c# .net xml xml-serialization


【解决方案1】:
[XmlArray("Hotels")]
[XmlArrayItem(typeof(Hotel), ElementName="Hotel")]
public HotelList[] Messages { get; set; }

应该产生:

<Hotels>
    <Hotel />
    <Hotel />
</Hotels>

[XmlRoot("Hotels")]
public class HotelList : IXmlSerializable
{
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        this.Hotels = XDocument.Load(reader)
                               .Select(h => new Hotel { Name = (string)h.Attribute("name") }
                               .ToList();
    }

    public void WriteXml(XmlWriter writer)
    {
        throw new NotSupportedException();
    }
}

【讨论】:

  • 我需要使用 List,而不是 HotelBasic[]
  • @odyodyodys: 1. XmlSerializer 仅支持数组。 2.您要求IEnumerable&lt;T&gt;,数组实现它。 3.你不想要List&lt;T&gt;,因为它是一个可消耗的容器,但xml中的列表是final。 4.您可以创建列表调用ToList()
  • 我正在使用 Lists 方法,例如 Find 等等。重新实现List 会很痛苦
  • @odyodyodys:你可以调用ToList().Find(...),或者不使用XmlSerializer和属性集,而只标记根元素并为自定义结构实现IXmlSerializable
  • @odyodyodys:我已经更新了我的答案如何实现IXmlSerializable
【解决方案2】:

假设您使用XmlSerializer,如果您只想更改HotelBasic 类的序列化方式,则可以使用XmlTypeAttribute

[XmlType(TypeName = "Hotel")]
public class HotelBasic
{
    public string Name { get; set; }
}

当与HotelList 类一起使用时,它将被序列化为:

<Hotels xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Hotel>
    <Name>One</Name>
  </Hotel>
  <Hotel>
    <Name>Two</Name>
  </Hotel>
</Hotels>

【讨论】:

    【解决方案3】:

    我认为 madd0 在这里为您显示了最简单的选项,但只是为了完整性......我个人不推荐“将列表序列化为根对象” - 出于各种原因(包括:我已经看到了这些属性至少在平台上不起作用 - 可能是 CF 或 SL,不记得了)。相反,我总是建议使用自定义根类型:

    [XmlRoot("Hotels")]
    public class HotelResult // or something similar
    {
        [XmlElement("Hotel")]
        public List<HotelBasic> Hotels { get { return hotel; } }
    
        private readonly List<HotelBasic> hotels = new List<HotelBasic>();
    }
    

    这将具有相同的 xml 结构,并允许更大的灵活性(您可以将其他属性/元素添加到根),并且不会将 List&lt;T&gt; 烘焙到您的类型模型中(更喜欢封装而不是继承等)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多