【问题标题】:XmlSerializer.Deserialize() behaves different between NECF 2.0 and NETCF 3.5XmlSerializer.Deserialize() 在 NECF 2.0 和 NETCF 3.5 之间表现不同
【发布时间】:2014-02-11 16:38:56
【问题描述】:

我正在将使用 Web 服务的旧 NETCF 2.0 应用程序迁移到 NETCF 3.5。外部服务器的 web 服务保持不变。此外,我使用 VS 2008 命令提示符新生成了 Reference.cs - 很高兴看到与使用 VS 2005 相同的结果。

我的问题与 webservice 定义的类在根标记处的命名空间定义有关。 java webservice 使用xmlns 属性对其进行序列化,NETCF 3.5 的XmlSerializer.Deserialize() 指责该属性引发InvalidOperationException。将此 XML 和 XmlSerializer.Deserialize() 与 NETCF 2.0 一起使用可以按预期工作。对象被反序列化到内存中。

让一些代码sn-ps让事情变得清晰。

异常

InvalidOperationException-There is an error in XML document (2, 2).
InnerException: InvalidOperationException-<InstallDirective xmlns='java:my.foreign.namespace'> was not expected. 
  at System.Xml.Serialization.XmlSerializer.resolveDeserializingType(XmlReader reader, XmlSerializationReader serialReader, Boolean soap12)
  at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
  at System.Xml.Serialization.XmlSerializer.Deserialize(Stream stream)
  at My.Neat.Software.Bug.Test()

生成的 Reference.cs(摘录)

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="java:my.foreign.namespace")]
public partial class InstallDirective {
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
    public System.Nullable<System.DateTime> Date;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
    public JustAnotherThing JustAnotherThing;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
    public System.Nullable<short> Oid;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
    public string Filename;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
    public string Version;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
    public string Dir;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
    public string Instructions;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Scripts", IsNullable=true)]
    public Script[] Scripts;
}

来自网络服务的 XML

<?xml version="1.0" encoding="utf-8"?>
<InstallDirective xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="java:my.foreign.namespace">
    <Date>2014-02-11T13:31:49.238+01:00</Date>
    <JustAnotherThing>
        <FileName>MyFunnyFile.txt</CabFileName>
        <Checksum>e759af8bd5787e3f8d62245a7d6aa73d</Checksum>
        <FileExists xsi:nil="true" />
        <Name>MyFunnyFile</Name>
        <Version>1.2</Version>
        <Path xsi:nil="true" />
        <DependsOn xsi:nil="true" />
        <RegistryPath xsi:nil="true" />
    </JustAnotherThing>
    <Oid>1</Oid>
    <Filename>MyFunnyFile.txt</Filename>
    <Version>1.2</Version>
    <Dir>\My\Path\To\Files</Dir>
    <Instructions xsi:nil="true" />
    <Scripts xsi:nil="true" />
</InstallDirective>

引发异常的代码sn-p

FileInfo directiveFile = new FileInfo(@"\tmp\install\funnyInstallDirective.xml");
XmlSerializer xmlSerializer = new XmlSerializer(typeof(InstallDirective));
TextReader reader = new StreamReader(directiveFile.OpenRead());
InstallDirective installDirective = (InstallDirective)xmlSerializer.Deserialize(reader); // BAM!

感谢您的帮助!

【问题讨论】:

    标签: web-services xml-serialization xml-namespaces invalidoperationexception .net-cf-3.5


    【解决方案1】:

    确实,.Net Compact Framework 2.0 和 3.5 的 XmlSerializer 实现有所不同。这种“新”行为的解决方案也很简单。因为 XmlSerializer - 在我的例子中 - 将 XML 序列化为“片段”,所以我们需要声明 XmlRootAttribute。这是由于缺少要在 Reference.cs 中序列化的类型的 XmlRootAttribute 注释。 为了向后兼容 NETCF 2.0 实现序列化的 XML,我们需要通过 InstallDirective (Reference.cs) 的定义添加命名空间。不幸的是,我没有找到以编程方式获得此信息的方法。

    之前:

    XmlSerializer xmlSerializer = new XmlSerializer(typeof(InstallDirective));
    FileStream file = File.Create(@"\tmp\install\funnyInstallDirective.xml");
    TextWriter writer = new StreamWriter(file);
    xmlSerializer.Serialize(writer, installDirective);
    

    之后:

    XmlRootAttribute att = new XmlRootAttribute(typeof(InstallDirective).Name);
    att.Namespace = "java:my.foreign.namespace";
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(InstallDirective), att);
    FileStream file = File.Create(@"\tmp\install\funnyInstallDirective.xml");
    TextWriter writer = new StreamWriter(file);
    xmlSerializer.Serialize(writer, installDirective);
    

    感谢ta.speot.is 回答了问题here

    [更新] 当然你可以使用web服务类型的带注释的XmlTypeAttribute来美化它。它看起来会这样。

    XmlTypeAttribute ta = (XmlTypeAttribute)Attribute.GetCustomAttribute(typeof(InstallDirective), typeof(XmlTypeAttribute));
    XmlRootAttribute att = new XmlRootAttribute(typeof(InstallDirective).Name);
    att.Namespace = ta.Namespace;
    XmlSerializer xmlSerializer = new XmlSerializer(typeof(InstallDirective), att);
    

    【讨论】:

      猜你喜欢
      • 2011-04-15
      • 1970-01-01
      • 1970-01-01
      • 2011-04-07
      • 2011-01-31
      • 2016-05-28
      • 2011-07-31
      • 1970-01-01
      • 2011-01-13
      相关资源
      最近更新 更多