2011-09-05 66 views
0

是否可以使用C#XmlSerialization API以两种不同的方式存储单个类? 例如C#xmlserialization以两种不同的方式存储一个类 - 可能吗?

class Test 
{ 
    int group1_attr1; 
    int group1_attr2; 
    int group2_attr1; 
} 

我想有一个方式如何类字段分成两个部分(组 - 具有指定属性),并且每个我请序列化到控制哪些部分将被存储的时间。例如,如果保存为1组

<?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> 

如果保存为组2

<?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实例中的最佳方式。 (请注意,组1和组2的字段不重叠)

+0

你为什么不存储这些propertys in List /Dictionary 并在序列化之前重新填充该集合?如果这确实是一个问题,你应该考虑重新设计。 – mbx

+0

如果您创建的接口描述您在不同接口中的属性组,您可能可以使用接口驱动的XML序列化来解决此问题(另外,接口支持多继承)。想想看。干杯;) –

回答

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; 
    } 
+0

谢谢,XmlAttributeOverrides是我在尝试之前尝试过的,但是我忽略了xa.XmlIgnore = true; 选项 - 谢谢指出。现在它似乎在工作。至于合并它 - 你的建议是我的想法,以及我无法在API中找到任何支持。从您的回复中我推断,序列化API中确实没有任何内容支持合并,因此XML合并是最佳方法。非常感谢! (源代码比我问的要多得多) – Peter

+0

@Peter - 请注意,如果您事实上确实如此,您可以接受它作为您的首选答案,这会将问题标记为已回答(并给出我一些观点,另一种表达方式)考虑回答的问题。 – BlueMonkMN

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()); 

但是,将它们重新放在一起仍然是您的问题。

0

可以loook到我的项目,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格式的工作:

/从XML使用IPersonRoot接口:

使用IPersonCustomRoot接口
 <Person> 
      <Name>John Doe</Name> 
     </Person> 

到/从XML:

 <Body> 
      <Name>John Doe</Name> 
     </Body> 

/从XML使用IPersonCustomAttribute接口:

 <Person Id="John Doe" /> 

有一个愉快的一天,

干杯;)

阿图尔·M.

+0

而且,因为代码越少越好。你没有花几个小时来完成这样一个简单的任务,我已经关注这个问题,建立了接口驱动的XML序列化框架;) –

相关问题