【问题标题】:XML Serialization of class collection in c#c#中类集合的XML序列化
【发布时间】:2011-09-15 10:21:40
【问题描述】:

我有一个包含对象集合的类。集合中的对象是同一类的后代。 A 类是基类,B 类和 C 类继承自 A 类。B 和 C 各有一些不同的成员。该集合是一个 LIst 集合。

我想序列化包含该集合的类。如何将不同的类归因于能够序列化和反序列化 xml 文件?

谢谢, 罗伯特

【问题讨论】:

  • 只需将[Serializable] 属性添加到类。
  • [Serializable] 显然不适用于 XML 序列化
  • 我的问题主要是关于两个多态后代类。
  • XmlSerializer 和 DataContractSerlizer 都支持 [Serializable]。 msdn.microsoft.com/en-us/library/…msdn.microsoft.com/en-us/library/…。类从其他类继承这一事实并不真正影响它们的可串行性。

标签: c# xml serialization


【解决方案1】:

[Serializable] 属性与 XML 序列化无关。 XML 序列化程序使用公共 getter AND setter 序列化属性。此外,您必须通过将Type[] 额外参数传递给序列化器ctor 或添加[XmlInclude(typeof(B))][XmlInclude(typeof(C))]

编辑:

以下代码:

[XmlInclude(typeof(B))]
[XmlInclude(typeof(C))]
public class A
{
    public int Value;
    public A() { }
    public A(int i) { Value = i; }
}

public class B : A
{
    public double DoubleValue;
    public B() { }
    public B(int i, double d) : base(i) { DoubleValue = d; }
}

public class C : A
{
    public string StringValue;
    public C() { }
    public C(int i, string s) : base(i) { StringValue = s; }
}

public class Container
{
    public List<A> Items;
    public Container()
    {
        Items = new List<A>();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Container container = new Container();
        container.Items.Add(new B(0, 1.3d));
        container.Items.Add(new B(1, 0.37d));
        container.Items.Add(new C(2, "c"));

        using (System.IO.StreamWriter writer = new System.IO.StreamWriter(@"C:\TEMP\Container.xml"))
        {
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Container));
            serializer.Serialize(writer, container);
        }
    }
}

产生那个xml:

<Container xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Items>
    <A xsi:type="B">
      <Value>0</Value>
      <DoubleValue>1.3</DoubleValue>
    </A>
    <A xsi:type="B">
      <Value>1</Value>
      <DoubleValue>0.37</DoubleValue>
    </A>
    <A xsi:type="C">
      <Value>2</Value>
      <StringValue>c</StringValue>
    </A>
  </Items>
</Container>

【讨论】:

  • +1 同意。唯一的要求 - 使用默认构造函数使类公开,并且不包含公开的不可序列化的可写属性
  • [XmlInclude(typeof(B))] 是我要找的。​​span>
【解决方案2】:

您可以使用 XmlSerialization 或 DataContract(或更“原始”的实现),请参阅:http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/

关于序列化:你只需要标记你想要序列化的类,所以你需要标记B类和C类,但你不需要标记A类。

不过,我建议您将 A 类标记为可序列化,从而让您和其他程序员更清楚该类支持序列化。

【讨论】:

  • 不。这取决于。您可能没有具有仍然能够使用 XML 序列化的属性的类
  • @Artur Mustafin:你说得对,我不应该在我的回答中使用“需要”。我将把我的答案留在那里,因为我仍然认为在大多数情况下,这是在序列化时设置类结构最清晰的方法。
【解决方案3】:

使用 Xml 序列化不需要属性类:

using System;
using System.IO;
using System.Xml.Serialization;

/* Three classes are included here. Each one will
be used to create three XmlSerializer objects. */

public class Instrument
{
   public string InstrumentName;
}

public class Player
{
   public string PlayerName;
}

public class Piece
{
   public string PieceName;
}

public class Test
{
   public static void Main()
   {
      Test t = new Test();
      t.GetSerializers();
   }

   public void GetSerializers()
   {
      // Create an array of types.
      Type[]types = new Type[3];
      types[0] = typeof(Instrument);
      types[1] = typeof(Player);
      types[2] = typeof(Piece);

      // Create an array for XmlSerializer objects.
      XmlSerializer[]serializers= new XmlSerializer[3];
      serializers = XmlSerializer.FromTypes(types);
      // Create one Instrument and serialize it.
      Instrument i = new Instrument();
      i.InstrumentName = "Piano";
      // Create a TextWriter to write with.
      TextWriter writer = new StreamWriter("Inst.xml");
      serializers[0].Serialize(writer,i);
      writer.Close();
   }
}

要使用集合,可以按如下方式序列化它:

using System;
using System.IO;
using System.Collections;
using System.Xml.Serialization;

public class Test{
    static void Main(){
        Test t = new Test();
        t.SerializeCollection("coll.xml");
    }

    private void SerializeCollection(string filename){
        Employees Emps = new Employees();
        // Note that only the collection is serialized -- not the 
        // CollectionName or any other public property of the class.
        Emps.CollectionName = "Employees";
        Employee John100 = new Employee("John", "100xxx");
        Emps.Add(John100);
        XmlSerializer x = new XmlSerializer(typeof(Employees));
        TextWriter writer = new StreamWriter(filename);
        x.Serialize(writer, Emps);
    }
}
public class Employees:ICollection{
    public string CollectionName;
    private ArrayList empArray = new ArrayList(); 

    public Employee this[int index]{
        get{return (Employee) empArray[index];}
    }

    public void CopyTo(Array a, int index){
        empArray.CopyTo(a, index);
    }
    public int Count{
        get{return empArray.Count;}
    }
    public object SyncRoot{
        get{return this;}
    }
    public bool IsSynchronized{
        get{return false;}
    }
    public IEnumerator GetEnumerator(){
        return empArray.GetEnumerator();
    }

    public void Add(Employee newEmployee){
        empArray.Add(newEmployee);
    }
}

public class Employee{
    public string EmpName;
    public string EmpID;
    public Employee(){}
    public Employee(string empName, string empID){
        EmpName = empName;
        EmpID = empID;
    }
}

【讨论】:

    猜你喜欢
    • 2012-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多