【问题标题】:how to use XmlAttributeOverrides when serializing an array?序列化数组时如何使用 XmlAttributeOverrides?
【发布时间】:2016-09-04 20:43:11
【问题描述】:

我有一个名为 _updatedComponents 的数组,其中包含 NetworkComponent 类的对象。我必须以更改根元素(=array)的名称和命名空间并将单个 NetworkComponent-item 的名称更改为组件的方式对其进行序列化。我下面有一个导致异常的代码:

System.InvalidOperationException:出现反映类型“ComponentSyncService.NetworkComponent[]”的错误。 ---> System.InvalidOperationException:不能为类型 ComponentSyncService.NetworkComponent[] 指定 XmlRoot 和 XmlType 属性。

代码:

XmlAttributeOverrides xaos = new XmlAttributeOverrides();

// the array itself aka the root. change name and namespace
XmlElementAttribute xea = new XmlElementAttribute(_updatedComponents.GetType());
xea.Namespace = "http://www.example.com/nis/componentsync";
xea.ElementName = "components";

XmlAttributes xas = new XmlAttributes();
xas.XmlElements.Add(xea);
xaos.Add(_updatedComponents.GetType(), xas); 

// then the items of the array. just change the name
xea = new XmlElementAttribute(typeof(networkcomponent));
xea.ElementName = "component";

xas = new XmlAttributes();
xas.XmlElements.Add(xea);
xaos.Add(typeof(NetworkComponent), "NetworkComponent", xas);

XmlSerializer serializer = new XmlSerializer(_updatedComponents.GetType(), xaos);

XmlTextWriter writer = new XmlTextWriter(string.Format("{0}\\ComponentSyncWS_{1}.xml", 
                      Preferences.FileSyncDirectory, requestId), Encoding.UTF8);
serializer.Serialize(writer, _updatedComponents);

【问题讨论】:

  • 我可能会补充一点,我不想更改 System.Xml.Serialization.XmlTypeAttribute 定义,因为生成了类,因此重新生成时更改将丢失

标签: c# .net xml-serialization


【解决方案1】:

_updatedComponents 是什么?我猜这是NetworkComponent[] - 这会让事情变得非常棘手。我建议编写一个包装器类型:

public class ComponentsMessage {
    public NetworkComponent[] Components {get;set;}
}

然后您可以关联正确的属性。如果您需要在 NetworkComponent 上支持 ad-hoc 属性,您仍然需要使用属性覆盖(因此我根本没有修饰上面的内容),但 ComponentsMessage 应该很乐意接受这些属性。

或者,只需编写一个单独的 DTO 并映射值。

如果它很简单,你也许可以使用:

[XmlRoot("components", Namespace = XmlNamespace)]
[XmlType("components", Namespace = XmlNamespace)]
public class ComponentsMessage
{
    public const string XmlNamespace = "http://www.example.com/nis/componentsync";
    [XmlElement("component")]
    public NetworkComponent[] Components { get; set; }
}

或者,如果您必须使用属性覆盖,我仍然会使用包装器对象:

public class ComponentsMessage
{
    public NetworkComponent[] Components { get; set; }
}
class Program
{
    static void Main()
    {
        NetworkComponent[] _updatedComponents = new NetworkComponent[2] {
            new NetworkComponent{},new NetworkComponent{}
        };
        const string XmlNamespace = "http://www.example.com/nis/componentsync";
        XmlAttributeOverrides ao = new XmlAttributeOverrides();
        ao.Add(typeof(ComponentsMessage), new XmlAttributes {
            XmlRoot = new XmlRootAttribute("components") { Namespace = XmlNamespace },
            XmlType = new XmlTypeAttribute("components") { Namespace = XmlNamespace }
        });
        ao.Add(typeof(ComponentsMessage), "Components", new XmlAttributes {
            XmlElements =  {
                new XmlElementAttribute("component")
            }
        });
        ComponentsMessage msg = new ComponentsMessage { Components = _updatedComponents };
        XmlSerializer serializer = new XmlSerializer(msg.GetType(), ao);
        serializer.Serialize(Console.Out, msg);
    }
}

【讨论】:

  • 感谢您的回答!正如我在问题中所说:“我有一个名为 _updatedComponents 的对象数组,这些对象属于 NetworkComponent 类。”我刚下班,所以我明天试试。太糟糕了,这很棘手。我不完全明白为什么......
  • 再次感谢!我会在早上第一件事检查你编辑的答案。
  • 我尝试了简单的版本,它成功了。多谢!你付出了很多努力来提供 XmlAttributeOverrides 版本。希望它能帮助真正需要它的人。
猜你喜欢
  • 1970-01-01
  • 2018-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多