XmlSerializer.Deserialize()在NECF 2.0和NETCF 3.5之间表现不同

时间:2014-02-11 16:38:57

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

我正在迁移旧的NETCF 2.0应用程序,该应用程序使用Web服务到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一起工作正常。对象被反序列化为内存。

让一些代码片段让事情变得清晰。

异常

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;
}

来自webservice的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>

抛出异常的代码片段

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!

感谢您的帮助!

1 个答案:

答案 0 :(得分: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.ishere的积分。

<强> [UPDATE] 当然,您可以使用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);