如何避免使用XML反序列化创建对象的多个实例?

时间:2010-08-20 22:05:25

标签: c# xml-serialization

我有一个类,当序列化为XML时看起来像这样(为简单起见而推广):

<root>
  <resources>
    <resource name="foo" anotherattribute="value">data</resource>
    <resource name="bar" anotherattribute="value">more data</resource>
  </resource>
  <myobject name="objName">
    <resource name="foo" />
  </myobject>
</root>

当反序列化时,我需要在resource实例的属性中引用的myobject实例与在resources集合的反序列化期间创建的对象相同。另外,如果可能的话,我不想在resource中输出myobject实例的完整序列化,只需输出名称。

有没有办法做到这一点?现在我正在考虑使用单独的字符串属性来进行序列化,当反序列化器设置属性时,它会从root获取相关对象,但这意味着为myobject提供对{{1}的引用包含它,我希望避免这种耦合。

1 个答案:

答案 0 :(得分:1)

你不能用XmlSerializer做到这一点,因为它不处理对象引用。

如果您对生成的架构没有任何约束,则可以使用DataContractSerializer,它也序列化为XML但支持引用。要使用DataContractSerializer,每种类型都必须具有DataContract属性,并且您要序列化的每个成员都必须具有DataMember属性:

[DataContract(Name = "root")]
public class root
{
    [DataMember]
    public List<resource> resources { get; set; }
    [DataMember]
    public myobject myobject { get; set; }
}

[DataContract]
public class myobject
{
    [DataMember]
    public string name { get; set; }
    [DataMember]
    public resource resource { get; set; }
}

[DataContract(Name = "resource", IsReference = true)]
public class resource
{
    [DataMember]
    public string name { get; set; }
    [DataMember]
    public string anotherattribute { get; set; }
    [DataMember]
    public string content { get; set; }
}

...

var serializer = new DataContractSerializer(typeof(root));
using (var xwriter = XmlWriter.Create(fileName))
{
    serializer.WriteObject(xwriter, r);
}

请注意IsReference = true类的resource:这是使序列化程序通过引用处理此类的原因。在生成的XML中,每个resource实例仅被序列化一次:

<?xml version="1.0" encoding="utf-8"?>
<root xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/">
  <myobject>
    <name>objName</name>
    <resource z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
      <anotherattribute>value</anotherattribute>
      <content>data</content>
      <name>foo</name>
    </resource>
  </myobject>
  <resources>
    <resource z:Ref="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" />
    <resource z:Id="i2" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
      <anotherattribute>value</anotherattribute>
      <content>more data</content>
      <name>bar</name>
    </resource>
  </resources>
</root>