让我说我有这个简单的(像联盟一样)C#struct
[StructLayout(LayoutKind.Explicit)]
public struct MyData
{
[FieldOffset(0)]
public int Num;
[FieldOffset(0)]
public int Number;
[FieldOffset(4)]
public string Name;
[FieldOffset(4)]
public string Url;
};
使用XmlSerializer和StreamWriter的保存方法
static void SaveToXml(object obj, string fileName)
{
XmlSerializer writer = new XmlSerializer(obj.GetType());
using (StreamWriter file = new StreamWriter(fileName))
{
writer.Serialize(file, obj);
}
}
因此,如果我们将一些数据放入并保存:
MyData md = new MyData();
md.Name = "Ilan_01";
md.Num = 1;
SaveToXml(md, @"C:\temp\data.xml");
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">
<Num>1</Num>
<Number>1</Number>
<Name>Ilan_01</Name>
<Url>Ilan_01</Url>
</MyData>
是否可以使它看起来像这样(使用相同或类似的方法)?
<?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">
<Num>1</Num>
<Name>Ilan_01</Name>
</MyData>
修改
另一方面,如果我们设置这些数据:
md = new MyData();
md.Url = "127.0.0.1";
md.Number = 2;
我希望看到这个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">
<Number>2</Number>
<Url>127.0.0.1</Url>
</MyData>
所以XmlIgnore
属性不是我想要的。
这只是一个简单的例子,真正的实现是使用不同类型(相同大小)的其他结构。
结束修改
谢谢,Ilan
答案 0 :(得分:1)
这是不可能的。如果您使用Url或Name来分配值,结构将不会记住,因此,Serializer也不会知道。
我能想到的最佳方式是,模仿该行为是将这些字段公开为属性,并在设置它们时记住哪个属性用于赋值(这需要一些额外的存储空间)。然后,您必须实现IXmlSerializable
并提供自己的编写XML的序列化,具体取决于您用于设置数据的属性。
我认为最好使用XmlIgnore
忽略重复字段,或者为名称和网址使用不同的结构。
答案 1 :(得分:1)
这不是你想要的,但可能是可扩展的,以满足你的需求,原始代码来自msdn的某个地方,不记得我害怕的地方。我确信必须有一种更优雅的方式(即在MyData的成员上有自定义属性),但我不知道:
public struct MyData
{
public int Num;
public int Number;
public string Name;
public string Url;
};
class XMLIgnore
{
static void SaveToXml(MyData obj)
{
XmlSerializer writer2 = customserialiser(obj);
writer2.Serialize(Console.Out, obj);
}
static public XmlSerializer customserialiser(MyData d)
{
XmlAttributes attrs = new XmlAttributes();
attrs.XmlIgnore = true;
XmlAttributeOverrides xmlOveride = new XmlAttributeOverrides();
if( d.Name.Length != 0 )
xmlOveride.Add(typeof(MyData), "Url", attrs);
else
xmlOveride.Add(typeof(MyData), "Name", attrs);
if (d.Num != 0)
xmlOveride.Add(typeof(MyData), "Number", attrs);
else
xmlOveride.Add(typeof(MyData), "Num", attrs);
return new XmlSerializer(typeof(MyData), xmlOveride);
}
public static void go()
{
MyData d = new MyData();
d.Num = 1;
d.Number = 2;
d.Name = "John";
d.Url = "Happy";
SaveToXml(d);
Console.WriteLine();
Console.WriteLine();
MyData d2 = new MyData();
d2.Num = 0;
d2.Number = 2;
d2.Name = "";
d2.Url = "Happy";
SaveToXml(d2);
}
}
答案 2 :(得分:0)
您是否尝试将[NonSerialized]属性添加到您不想要的字段?
答案 3 :(得分:0)
只需在您不希望序列化的字段上使用[XmlIgnore]
属性,如下所示:
[StructLayout(LayoutKind.Explicit)]
public struct MyData
{
[FieldOffset(0)]
public int Num;
[FieldOffset(0)]
[XmlIgnore]
public int Number;
[FieldOffset(4)]
public string Name;
[FieldOffset(4)]
[XmlIgnore]
public string Url;
};
答案 4 :(得分:0)
您可以在不想序列化的属性上使用XmlIgnore
属性。
答案 5 :(得分:0)
谢谢Patrick
以下是我调整后的例子:
public struct SimpleStruct1
{
public int Number;
public byte Channel;
}
public struct SimpleStruct2
{
public int ID;
public byte Mode;
}
public enum StructType
{
ST_1=0, ST_2,
}
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct MyData
{
[FieldOffset(0)]
public int ID;
[FieldOffset(4)]
public StructType structType;
[FieldOffset(8)]
[XmlElement(ElementName="SimpleStruct1")]
public SimpleStruct1 ss1;
[FieldOffset(8)]
[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), "ss1", attrs);
break;
default:
break;
}
return new XmlSerializer(typeof(MyData), xmlOveride);
}
}
static void SaveToXml(object obj, string fileName, XmlSerializer writer)
{
using (StreamWriter file = new StreamWriter(fileName))
{
writer.Serialize(file, obj);
}
}
static void Main(string[] args)
{
SimpleStruct1 sStrct1 = new SimpleStruct1();
sStrct1.Channel = 15;
sStrct1.Number = 35;
MyData md1 = new MyData();
md1.ID = 1;
md1.structType = StructType.ST_1;
md1.ss1 = sStrct1;
XmlSerializer writer = XMLIgnore.customserialiser(md1);
SaveToXml(md1, @"C:\temp\dataOne.xml", writer);
SimpleStruct2 sStrct2 = new SimpleStruct2();
sStrct2.ID = 74;
sStrct2.Mode = 2;
MyData md2 = new MyData();
md2.ID = 2;
md2.structType = StructType.ST_2;
md2.ss2 = sStrct2;
writer = XMLIgnore.customserialiser(md2);
SaveToXml(md2, @"C:\temp\dataTwo.xml", writer);
}