【问题标题】:Order XML elements for serialization订购 XML 元素以进行序列化
【发布时间】:2017-03-10 10:54:57
【问题描述】:

我必须按特定顺序将我的对象序列化为 XML 文档。

<?xml version="1.0"?>
<__Root __version="1.1" __encryption="2">
  <__service __serviceType="Test">
  <__inputData>
   <BaseToChange>
    <__name>TestName</__name>
   </BaseToChange>
  </__inputData>
  <__perform> 
   <__eventName>Event</__eventName>
  </__perform>    
  <__inputData>
      <ObjectChanges>
        <Name>Test</Name>
      </ObjectChanges>
    </__inputData>
    <__execute />
    <__requestData>
      <CompletionMsg />
    </__requestData>
  </__service>
</__Root>

我现在遇到的问题是,我无法将我的 List&lt;InputData&gt; 与介于两者之间的元素 Perform 序列化。

public class Service
{
    [XmlAttribute("__serviceType")]
    public string ServiceType { get; set; }

    [XmlElement("__perform")]
    public Perform Perform { get; set; }

    [XmlElement("__inputData")]
    public List<InputData> InputData{ get; set; }

    [XmlElement("__execute")]
    public Execute Execute { get; set; }

    [XmlElement("__requestData")]
    public RequestData RequestData{ get; set; }

    public Service() { }
}

顺序必须如图所示。所以首先是&lt;__inputData&gt;,然后是&lt;__perform&gt;,然后是剩余的&lt;__inputData&gt;

我已经尝试将 Properties 和 XmlElements 分开,但是一旦我想用两个具有相同名称的元素进行序列化,我就会收到错误。

有人知道如何实现吗?

【问题讨论】:

  • 中间是什么意思?您是指列表中的第 1 项,然后执行,然后是列表中的第 2 项吗?听起来你的结构应该重新设计
  • @Ofir Winegarden:没错。我需要这种结构,否则我尝试在(通过 XML)中创建对象的系统会引发错误。
  • 1) 您想如何控制&lt;__perform&gt; 元素的出现位置?它总是在第一个&lt;__inputData&gt; 之后,还是会有所不同? 2) 你的InputData 类型是什么样的?它似乎有时有一个&lt;BaseToChange&gt; 元素,有时还有一个&lt;ObjectChanges&gt; 元素?
  • 顺序必须如图所示。所以首先是&lt;__inputData&gt;,然后是<__perform>``,然后是&lt;__inputData&gt;。 'InputData' 的类型确实有两个对象:BaseToChangeObjectChanges

标签: c# xml serialization


【解决方案1】:

您可以利用多态元素功能[XmlElement(Type = typeof(TElement))] 创建一个代理对象数组,其中包含PerformInputData 对象,顺序正确:

public class Service
{
    [XmlAttribute("__serviceType")]
    public string ServiceType { get; set; }

    [XmlIgnore]
    public Perform Perform { get; set; }

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

    [XmlElement("__perform", Type = typeof(Perform))]
    [XmlElement("__inputData", Type = typeof(InputData))]
    public object[] XmlInputAndPerformance
    {
        get
        {
            var inputData = (InputData ?? Enumerable.Empty<InputData>()).Cast<object>();
            var performData = Perform == null ? Enumerable.Empty<object>() : new object[] { Perform };

            return inputData.Take(1)
                .Concat(performData)
                .Concat(inputData.Skip(1))
                .ToArray();
        }
        set
        {
            if (value == null)
                return;
            var newInputs = value.OfType<InputData>().ToList();
            var newPerform = value.OfType<Perform>().ToList();
            if (newInputs.Count + newPerform.Count != value.Length)
                throw new ArgumentException("Unknown type.");
            if (newPerform.Count > 1)
                throw new ArgumentException("Too many Perform objects.");

            if (newPerform.Count > 0)
                Perform = newPerform[0];
            (InputData = InputData ?? new List<InputData>()).AddRange(newInputs);
        }
    }

    [XmlElement("__execute")]
    public Execute Execute { get; set; }

    [XmlElement("__requestData")]
    public RequestData RequestData { get; set; }

    public Service() { }
}

请注意,原来的InputDataPerform 属性已被标记为[XmlIgnore],并且添加了两个[XmlElement(name, Type = typeof(TElement))] 属性,一个用于InputData,一个用于Perform

示例fiddle

【讨论】:

  • 像魅力一样工作。谢谢。
猜你喜欢
  • 2011-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-30
  • 2011-06-24
  • 2013-12-06
相关资源
最近更新 更多