XmlSerializer Error, bytes array, List and InvalidOperationE

本文关键字:and InvalidOperationE List bytes Error XmlSerializer array | 更新日期: 2023-09-27 18:35:01

我在 C# 中使用 XmlSerializer 发现了一种奇怪的行为,有人帮助我吗?我想要 SOAP/MTOM 中的 XML,我需要 xop:Include 在任何其他 XML 之外:

<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xop:Include href="cid:http://tempuri.org/1/635913361387292553" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
    <List>1</List>
    <List>2</List>
</Root>

这是我的 C# 代码:

public static void Main(string[] args)
{
    var simulatedFile = new byte[800];
    new Random().NextBytes(simulatedFile);
    var root = new Root {List = new List<string> {"1","2"}, Bytes = simulatedFile};
    XmlSerializer ser = new XmlSerializer(typeof(Root));
    using (var mtomInMemory = new MemoryStream())
    {
        using (var writer = XmlDictionaryWriter.CreateMtomWriter(mtomInMemory, Encoding.UTF8, int.MaxValue, string.Empty))
        {
            ser.Serialize(writer, root);
        }
        Console.WriteLine(Encoding.UTF8.GetString(mtomInMemory.ToArray()));
    }
    Console.Read();
}
public class Root
{
    [XmlText]
    public byte[] Bytes { get; set; }
    [XmlElement]
    public List<string> List { get; set; }
}

我遇到的错误是:

"System.InvalidOperationException"发生在System.Xml中.dll 是反映类型"程序.根"的错误。无法序列化对象 类型为"程序.根"。考虑更改 XmlText 成员的类型 "Program.Root.Bytes" 从 System.Byte[] 到字符串或字符串数组。

但是我需要让我的字节数组包含文件二进制文件,因为使用 MTOM,如果长度小于 768 字节,它将由 CreateMtomWriter 在 base64 中序列化,如果超过 768 字节,则由 xop:Include 序列化。

我希望它被编码为根元素的直接子元素,而不是包装在任何其他元素中。

如果在类 Root 中,我只放置了 Bytes 或 List 属性,它就可以完美地工作,但如果我同时放置两者,它就不能。

XmlSerializer Error, bytes array, List and InvalidOperationE

您似乎遇到了一个XmlSerializer错误。

如果我更改类以删除 List 属性,如下所示:

public class Root
{
    [XmlText]
    public byte[] Bytes { get; set; }
}

然后XmlSerializer将成功序列化它,字节数组自动表示为 base 64 字符串:

<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">AAECAwQFBgcICQ==</Root>

相反,如果我更改类以使 XmlText 属性成为将字节数组从 base 64 转换为 base 64 的string值代理属性,则XmlSerializer再次成功且相同地序列化它:

public class Root
{
    [XmlIgnore]
    public byte[] Bytes { get; set; }
    [XmlText]
    public string Base64Bytes
    {
        get
        {
            return Bytes == null ? null : Convert.ToBase64String(Bytes);
        }
        set
        {
            Bytes = value == null ? null : Convert.FromBase64String(value);
        }
    }
    [XmlElement]
    public List<string> List { get; set; }
}

事实上,XmlTextAttribute.DataType的文档清楚地表明字节数组是[XmlText]支持的数据类型之一。 Neverthess,[XmlText] byte [] Byte { get; set; }属性与同一类中的任何其他[XmlElement]属性的组合会导致XmlSerializer构造函数引发异常。 您可能希望向Microsoft报告问题,因为没有理由不这样做。

同时,可以使用字符串值代理属性的解决方法,如上所示。

从 Microsoft:感谢您报告此问题。这是设计使然。字节数组不能是文本值。请尝试解决此问题,例如使用字符串。