【发布时间】:2011-07-19 16:09:50
【问题描述】:
假设我们有一个结构,它的数据由使用 Marshal.PtrToStructure 的非托管字节数组提供。
C# 结构布局:
[StructLayout(LayoutKind.Sequential, Size = 128, CharSet = CharSet.Ansi, Pack = 1)]
public struct MNG_Y_Params
{
public byte Number;
public byte Version;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] OliNumber;
public byte InterfaceType;
}
字节数组表示非托管代码中的(ascii)字符串。
此结构是另一个结构的成员(具有其他一些成员):
public struct MyData
{
public int ID;
public StructType structType;
[XmlElement(ElementName="MNG_Y_Params")]
public MNG_Y_Params y_params;
[XmlElement(ElementName = "SimpleStruct2")]
public SimpleStruct2 ss2;
};
所以我们也有这个支持代码
public class XMLIgnore
{
static public XmlSerializer customserialiser(MyData d)
{
XmlAttributes attrs = new XmlAttributes();
attrs.XmlIgnore = true;
XmlAttributeOverrides xmlOveride = new XmlAttributeOverrides();
switch (d.structType)
{
case StructType.ST_1:
xmlOveride.Add(typeof(MyData), "ss2", attrs);
break;
case StructType.ST_2:
xmlOveride.Add(typeof(MyData), "y_params", attrs);
break;
default:
break;
}
return new XmlSerializer(typeof(MyData), xmlOveride);
}
}
以及保存方法
static void SaveToXml(object obj, string fileName, XmlSerializer writer)
{
//XmlSerializer writer = new XmlSerializer(obj.GetType());
using (StreamWriter file = new StreamWriter(fileName))
{
writer.Serialize(file, obj);
}
}
对于示例,我们只生成一些数据。
MNG_Y_Params yParams = new MNG_Y_Params();
yParams.Version = 1;
yParams.InterfaceType = 15;
yParams.Number = 35;
ASCIIEncoding enc = new ASCIIEncoding();
yParams.OliNumber = enc.GetBytes("#1");
MyData md1 = new MyData();
md1.ID = 1;
md1.structType = StructType.ST_1;
md1.y_params = yParams;
XmlSerializer writer = XMLIgnore.customserialiser(md1);
SaveToXml(md1, @"C:\temp\dataOne.xml", writer);
预期的 XML:
<?xml version="1.0" encoding="utf-8"?>
<MyData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>1</ID>
<structType>ST_1</structType>
<MNG_Y_Params>
<Number>35</Number>
<Version>1</Version>
<OliNumber>#1</OliNumber>
<InterfaceType>15</InterfaceType>
</MNG_Y_Params>
</MyData>
结果 XML:
<?xml version="1.0" encoding="utf-8"?>
<MyData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>1</ID>
<structType>ST_1</structType>
<MNG_Y_Params>
<Number>35</Number>
<Version>1</Version>
<OliNumber>IzE=</OliNumber>
<InterfaceType>15</InterfaceType>
</MNG_Y_Params>
</MyData>
请关注字节数组成员(OliNumber)结果。
我们可以在这里使用一个属性吗? 我错过了什么?
感谢您的时间和帮助。
宜兰
【问题讨论】:
-
反序列化时,OliNumber中的数据和序列化前的数据有区别吗? XML中的值可能很好,可能只是XMLSerializer用于字节数组的格式。
-
@Kipotlov 感谢您的评论。反序列化工作正常,但重点是在 XML 中表示来自非托管代码的数据,其中字节数组表示(ascii)字符串。
-
序列化程序将
byte[]视为二进制数据而不是字符串,因此它使用传输编码(base64)来允许任意二进制数据通过XML。请阅读规范,XML 不允许内容中包含大多数非打印字符。如果您要发送字符串,请将其命名为String。 -
我知道这是旧的,但我相信如果你改变你的编码... 到 utf-16,它可能会工作.您没有讨论基本字符集,因此您可能会在 XML 转换器中遇到问题。我在处理来自其他语言集的翻译时遇到了这个问题。 utf-16 拾取双字节字符,而 utf-8 没有。
标签: c# xml serialization unmanaged