2011-09-15 4 views
0

У меня есть класс, содержащий коллекцию объектов. Объекты в коллекции являются потомками одного и того же класса. Класс A - это базовый класс, а класс B и класс C наследуются от класса A. В B и C каждый имеет несколько разных членов. Коллекция - коллекция LIst.XML Сериализация коллекции классов в C#

Я хотел бы сериализовать класс, содержащий коллекцию. Как я могу приписать различным классам возможность сериализации и десериализации файла xml?

Спасибо, Роберт

+1

Просто добавьте '[Serializable]' атрибут к классу , –

+0

[Serializable] не применим к XML-сериализации, видимо, –

+0

. Мой вопрос в основном касается двух полиморфных классов потомков. –

ответ

0

Вы можете использовать либо XmlSerialization или DataContract (или более «примитивной» реализации), см: http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/

Что касается сериализации: вам нужно всего лишь отметить классы, которые требуется сериализуйте, поэтому вам нужно отметить классы B и C, но вы не обязаны отмечать класс A.

Я бы рекомендовал вам пометить класс А как сериализуемый и, следовательно, сделать более понятным для вас и других программистов, что этот класс поддерживает сериализацию.

+0

Nope. Это зависит. У вас могут не быть классов с атрибутами, которые все еще могут использовать сериализацию XML. –

+0

@Artur Mustafin: ваше право, я не должен использовать «необходимость» в своем ответе. Я оставлю свой ответ там, так как я все еще думаю, что это в большинстве случаев самый ясный способ для настройки структуры вашего класса при сериализации. – Polity

3

[Serializable] атрибут не имеет отношения к сериализации XML. Сериализатор XML сериализует свойства с помощью публичного getter и setter. Кроме того, вы должны сказать в XML сериализатор дополнительных типов, он мог бы использовать, те, которые не известны статический, пропускание Type[] дополнительного аргумента в сериализаторе CTOR или добавлении [XmlInclude(typeof(B))] и [XmlInclude(typeof(C))]

EDIT:

следующий код:

[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> 
+0

+1 Договорная. Единственные требования - сделать класс общедоступным с конструктором по умолчанию и не содержит общедоступных несериализуемых свойств записи –

+0

'[XmlInclude (typeof (B))] - это то, что я ищу. – mammadalius

-1

Вам не нужно приписывать классы использовать 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; 
    } 
} 
Смежные вопросы