是否可以使用C#XmlSerialization API以两种不同的方式存储单个类? 例如
class Test
{
int group1_attr1;
int group1_attr2;
int group2_attr1;
}
我想知道如何将类字段分成两部分(组 - 具有指定的属性),每次调用Serialize来控制将存储哪个部分。例如,如果保存为group1
<?xml version="1.0" encoding="utf-8"?>
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org /2001/XMLSchema">
<group1_attr1>0</group1_attr1>
<group1_attr2>0</group1_attr2>
</Test>
如果保存为group2
<?xml version="1.0" encoding="utf-8"?>
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org /2001/XMLSchema">
<group2_attr1>0</group2_attr1>
</Test>
有没有办法以“干净”的方式做到这一点?如果不是在xmlserialization中,那么也许在二进制中? 然后我想知道如何将这两个文件合并到单个Test实例中的最佳方法是什么。 (请注意,group1和group2中的字段不重叠)
答案 0 :(得分:1)
这里的代码演示了如何序列化,但是,反序列化将更加棘手,因为反序列化到现有实例并不简单(参见How to use XmlSerializer to deserialize into an existing instance?)。
public class Test
{
public int group1_attr1;
public int group1_attr2;
public int group2_attr1;
}
class Program
{
static void Main(string[] args)
{
System.Xml.Serialization.XmlAttributes xa =
new System.Xml.Serialization.XmlAttributes();
xa.XmlIgnore = true;
System.Xml.Serialization.XmlAttributeOverrides xo1 =
new System.Xml.Serialization.XmlAttributeOverrides();
xo1.Add(typeof(Test), "group1_attr1", xa);
xo1.Add(typeof(Test), "group1_attr2", xa);
System.Xml.Serialization.XmlAttributeOverrides xo2 =
new System.Xml.Serialization.XmlAttributeOverrides();
xo2.Add(typeof(Test), "group2_attr1", xa);
System.Xml.Serialization.XmlSerializer xs1 =
new System.Xml.Serialization.XmlSerializer(typeof(Test), xo1);
System.Xml.Serialization.XmlSerializer xs2 =
new System.Xml.Serialization.XmlSerializer(typeof(Test), xo2);
Test t1 = new Test();
t1.group1_attr1 = 1;
t1.group1_attr2 = 2;
t1.group2_attr1 = 3;
using (System.IO.StringWriter sw = new System.IO.StringWriter())
{
xs1.Serialize(sw, t1);
Console.WriteLine(sw);
}
using (System.IO.StringWriter sw = new System.IO.StringWriter())
{
xs2.Serialize(sw, t1);
Console.WriteLine(sw);
}
}
}
反序列化可以在反序列化之前合并XML:
Test t2 = new Test();
System.Xml.Serialization.XmlSerializer xs3 = new System.Xml.Serialization.XmlSerializer(typeof(Test));
string mergedXml = MergeSerializedXml(group1, group2);
using (System.IO.StringReader sr = new System.IO.StringReader(mergedXml))
{
t2 = (Test)xs3.Deserialize(sr);
}
...
static string MergeSerializedXml(string x1, string x2)
{
System.Xml.XmlDocument xd = new System.Xml.XmlDocument();
xd.LoadXml(x1);
System.Xml.XmlReaderSettings xrs = new System.Xml.XmlReaderSettings();
xrs.IgnoreWhitespace = true;
using (System.Xml.XmlReader xr = System.Xml.XmlReader.Create(new System.IO.StringReader(x2), xrs))
{
while (xr.Read() && !xr.IsStartElement())
;
xr.MoveToContent();
xr.Read();
System.Xml.XmlNode xn = xd.ChildNodes[1];
do
{
xn.AppendChild(xd.ReadNode(xr));
} while (xr.NodeType != System.Xml.XmlNodeType.EndElement);
}
return xd.OuterXml;
}
答案 1 :(得分:0)
组合将允许您执行此操作,http://en.wikipedia.org/wiki/Composition_over_inheritance。如果您序列化CompositeGroup1
,请将其粘贴到CompositeData
的实例中。对CompositeGroup2
执行相同操作。正如您所说,使用内置的序列化器无法满足您的要求。序列化数据时,它将始终生成该类型的完整序列化。
class CompositeData
{
public CompositeGroup1 Group1 { get; set; }
public CompositeGroup2 Group2 { get; set; }
}
class CompositeGroup1
{
public int Attr1 { get; set; }
public int Attr2 { get; set; }
}
class CompositeGroup2
{
public int Attr1 { get; set; }
}
您还可以考虑让CompositeData
实现抽象类,每个分组一个。您可以使用其他一些使用传入类型而不是运行时类型的JSON序列化程序来生成序列化数据。
var json1 = serializer.Serialize<AbstractGroup1>(new CompositeData());
var json2 = serializer.Serialize<AbstractGroup2>(new CompositeData());
然而,将它们重新组合在一起仍然是你的问题。
答案 2 :(得分:0)
你可以进入我的项目Xml Serialization Framework,它将使用接口习语来解决你可能遇到的同样问题
示例:
序列化类实例/对象
class Person
{
public string Name { get; set; }
}
你可能会声明在元数据驱动的xml运行时序列化中使用的接口:
interface IPersonRoot
{
string Name { get; set; }
}
[XmlRootSerializer("Body")]
interface IPersonCustomRoot
{
string Name { get; set; }
}
interface IPersonCustomAttribute
{
[XmlAttributeRuntimeSerializer("Id")]
string Name { get; set; }
}
该框架甚至支持使用特定接口/ XML格式部分更新活动实例:
使用IPersonRoot接口进出XML:
<Person>
<Name>John Doe</Name>
</Person>
使用IPersonCustomRoot接口进出XML;
<Body>
<Name>John Doe</Name>
</Body>
使用IPersonCustomAttribute接口进出XML:
<Person Id="John Doe" />
度过愉快的一天,
干杯;)
Artur M。