WinRT XmlAnyElement和序列化

时间:2014-01-21 22:29:08

标签: windows-runtime xml-serialization xmlanyelement

我们有一个Windows应用商店应用程序,它使用XML进行请求/响应与我们的服务器通信,并使用XmlSerializer进行序列化。我们遇到的问题是我们的一个类型可以包含任意XML作为其属性之一。在非WinRT应用程序中,用法就是。

public sealed ItemExtension {
    [XmlAttribute("source")]
    public string Source {get;set;}

    [XmlAnyElement]
    public XmlElement[] Data {get;set;}
}

这将允许我们在数据库中使用XML,如

<extension source="foo"><randomXml><data/></randomXml></extension>

在WinRT中,不包含XmlElement,System.Xml.XmlElement不存在且Windows.Data.Xml.Dom.XmlElement不兼容。文档提到XElement,但XElement不是受支持的WinRT类型,因此如果我尝试使用它,WinRT项目将无法编译。

这是Windows应用商店应用程序的错误还是有足够的解决方法?

感谢。

1 个答案:

答案 0 :(得分:0)

到目前为止,我只是找到了一个能够让它工作的黑客。如果我们使用

[XmlAnyElement]
public object Data {get;set;}

这将正确地反序列化现有数据。在检查它时,它在调试器中是System.Xml.XmlElement类型,它在WinRT中不公开。所以没有办法直接设置它。由于我们发现XmlSerializer可以实例化并访问System.Xml.XmlElement,我们使用它来处理设置它,方法是接受一个object / xml片段,将其包装在容器xml中,以获得包含[XmlAnyElement]并调用Deserialize的包装类型它让XmlSerializer实例化一个XmlElement,然后可以在你希望序列化的目标对象上设置它。

为了获取数据,因为尝试读取此属性会在UI层中引发异常,并且尝试访问InnerXml / OuterXml也会抛出异常,我们将使用XmlSerializer将XmlElement序列化为字符串,然后可以随意使用它。

public sealed class XmlAnyElementContainer
{
    [XmlAnyElement]
    public object Data { get; set; }
}

public void SetData(object extensionObject)
{
    var objectSerializer = new XmlSerializer(extensionObject.GetType());

    var settings = new XmlWriterSettings()
    {
        Indent = false,
        OmitXmlDeclaration = true
    };

    var sb = new StringBuilder();
    using (var xmlWriter = XmlWriter.Create(sb, settings))
    {
        objectSerializer.Serialize(xmlWriter, extensionObject);
    }

    string objectXml = sb.ToString();

    string newXml = "<XmlAnyElementContainer>" + objectXml + "</XmlAnyElementContainer>";
    var xmlAnySerializer = new XmlSerializer(typeof(XmlAnyElementContainer));
    using (var sr = new StringReader(newXml))
    {
        [TargetPropertyToSerialize] = (xmlAnySerializer.Deserialize(sr) as XmlAnyElementContainer).Data;
    }
}