【问题标题】:XML serialization of enums枚举的 XML 序列化
【发布时间】:2010-10-08 13:03:37
【问题描述】:

我在序列化枚举值时遇到问题。

代码如下:

[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public class REQUEST
{
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string ID;

    [System.Xml.Serialization.XmlAttributeAttribute()]
    public REQUESTTypetype Type;
}

public enum REQUESTTypetype
{
    One,
    Two,
    Three,
    Four,
}

...

REQUEST request = new REQUEST();
request.ID = "1234";
request.Type = REQUESTTypetype.One;

XmlDocument doc = new XmlDocument();
MemoryStream ms = new MemoryStream();
StreamWriter sw = new StreamWriter(ms);
XmlSerializer xs = new XmlSerializer(typeof(REQUEST));
xs.Serialize(sw, request_group);
ms.Position = 0;
doc.Load(ms);
TestWriteXml(doc, @"C:\xml_test.xml");

结果是:

<?xml version="1.0" encoding="utf-8" ?> 
<REQUEST ID="1234" />

为什么枚举没有序列化?我使用 .NET Framework 2.0。

谢谢。

【问题讨论】:

  • 我猜您的代码中缺少某些内容,您正在序列化“xs.Serialize(sw, request_group)”,但您设置了“请求”的值。 request_group的定义是什么,有没有设置类型?
  • 应该是“request”,我只是稍微改了一下名字。
  • TestWriteXml 函数的代码是什么?
  • public static void TestWriteXml(XmlDocument xml, string filename) { FileStream fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write); StreamWriter sw = new StreamWriter(fileStream); sw.WriteLine(xml.InnerXml); sw.Flush(); sw.Close(); }
  • VladV,我尝试了 [System.Xml.Serialization.XmlElement()] 而不是 [System.Xml.Serialization.XmlAttributeAttribute()] 但没有结果。

标签: c# enums xml-serialization


【解决方案1】:

我发现了问题所在。对于每个枚举类型

[System.Xml.Serialization.XmlAttributeAttribute()]
public REQUESTTypetype Type;

我知道了:

[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool TypeSpecified;

在代码中我应该这样做:

request.Type = REQUESTTypetype.One;
request.TypeSpecified = true;

现在可以正常使用了。我应该在我的问题中发布它们,但我根本没有注意这些“指定”成员。 感谢您的回复。

【讨论】:

    【解决方案2】:

    当您将类型设置为“二”或“三”时,您是否看到同样的问题?是因为“一”是默认值,所以可以假设?将其加载到 XmlDocument 中,然后使用您未显示的代码 (TestWriteXml) 保存它可能是一些人工制品。

    您的代码的这个稍微修改过的版本(我正在写入 StringBuilder,然后在最后将其 ToString 化)...

        REQUEST request = new REQUEST();
        request.ID = "1234";
        request.Type = REQUESTTypetype.One;
    
    
        StringBuilder sb = new StringBuilder();
        StringWriter sw = new StringWriter(sb);
        XmlSerializer xs = new XmlSerializer(typeof(REQUEST));
        xs.Serialize(sw, request);
        Console.WriteLine(sb.ToString());
    

    ...使用与您上面提到的完全相同的类型似乎可以正常工作。我在控制台得到这个...

    <?xml version="1.0" encoding="utf-16"?>
    <REQUEST xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http:/
    /www.w3.org/2001/XMLSchema" ID="1234" Type="One" />
    

    我没有更改 REQUEST 的定义或枚举 REQUESTTypetype。

    【讨论】:

    • 我只是在做同样的事情并得到同样的基本结果。我认为问题出在您的 TestWriteXml 函数中。
    • 我刚刚尝试了我在这里给出的示例,它工作正常。但是,我的 xml 比这要大得多,其中包含许多派生元素等,并且序列化忽略了结果 XML 中的每个枚举类型。知道我应该发布代码的哪一部分以使事情更清楚吗?
    • 我建议从您的示例开始并重新添加内容,直到它不再起作用。我猜想某处(子或孙类)缺少属性,或清除某些东西。
    【解决方案3】:

    您可以使用 Xml.Serialization.XmlEnum 属性 (see here) 来装饰枚举的值。

    Kurt Claeys here 的博客文章也可能有所帮助。

    【讨论】:

      【解决方案4】:

      在你的实际代码中,是成员:

      • 公开
      • 读+写(对于字段:非只读;对于属性:public get+set)
      • 公共类型

      ?

      这三个都必须是真的。对于嵌套类型,嵌套中的每个父类型都必须是公共的。

      排除它的其他内容:

      • 可空和空
      • 如果是默认值
      • ShouldSerialize 或 Specified 返回 false
      • 它是 IxmlSerializable

      【讨论】:

      • 另外,对于类(不是枚举),必须有一个公共的无参数构造函数。
      【解决方案5】:

      尝试将 [Flags] 属性放在枚举上。

      【讨论】:

      • 这与序列化完全无关。
      • @vladv - 虽然它可能不适用于此处,但有时 [Flags] 对序列化很重要。 IMO 是一个需要检查的有效答案,尤其是考虑到“长尾”。
      猜你喜欢
      • 2012-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-22
      • 1970-01-01
      • 2017-06-10
      相关资源
      最近更新 更多