2011-01-11 15 views
9

próbuję uruchomić kod podobny do tego:Serializacja interfejsy

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

namespace ConsoleApplication1 
{ 
    [Serializable] 
    [XmlInclude(typeof(List<Class2>))] 
    public class Class1 
    { 
     private IList<Class2> myArray; 

     public IList<Class2> MyArray 
     { 
      get { return myArray; } 
      set { myArray = value; } 
     } 

    } 

    public class Class2 
    { 
     private int myVar; 

     public int MyProperty 
     { 
      get { return myVar; } 
      set { myVar = value; } 
     } 

    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      XmlSerializer ser = new XmlSerializer(typeof(Class1), new Type[] { typeof(List<Class2>) }); 
      FileStream stream = File.OpenWrite("Data.xml"); 
      ser.Serialize(stream, new List<Class1>()); 
      stream.Close(); 
     } 
    } 
} 

Czy ktoś mógłby mi wyjaśnić, co robię źle?

dostaję:

Nie można szeregować członek .. MyArray ... bo to jest interfejs.

Czy XmlInclude nie powinien tego rozwiązać?

+0

Ktokolwiek powiedział coś o deserializacji ...? –

Odpowiedz

13

Nie. Nie można serializować interfejsu. Zawsze. Po prostu ci to powiedział.

Interfejs to nic innego jak opis zestawu zachowań. Nie mówi nic o zawartości instancji. W szczególności, chociaż instancja klasy implementującej interfejs musi implementować wszystkich jej członków, z pewnością będzie miała własne właściwości, które wymagają serializacji.

W jaki sposób zostałby zserializowany?

Jakiej klasy można użyć do deserializacji interfejsu po drugiej stronie?

+0

Jakiekolwiek obejścia? – Shahar

+3

@Shahar: tak. Nie rób tego. Użyj typu betonu, a nie interfejsu. –

+1

W jaki sposób zostałby zserializowany? Jako instancja klasy, która była serializowana, tak samo jak lista . Jakiej klasy można użyć do deserializacji interfejsu po drugiej stronie? Zobacz pierwszą odpowiedź. – jwg

0

Dołączyłeś typeof (List < ...>), ale MyArray jest typu IList < ...> który nie jest strukturą danych, ale raczej jest symbolem zastępczym do przyjęcia struktury danych.

Zmień typ MyArray na określony typ (jako List, np.) I powinien działać.

private List<Class2> myArray; 

    public List<Class2> MyArray 
    { 
     get { return myArray; } 
     set { myArray = value; } 
    } 
10

Oto niesprawdzone zacieniony obejście, że mają tendencję do korzystania z zasady:

private IList<Class2> myArray; 
[XmlIgnore] 
public IList<Class2> MyArray 
{ 
    get { return myArray; } 
    set { myArray = value; } 
} 

[XmlElement("MyArray")] 
public object MyArraySerializable 
{ 
    get { return MyArray; } 
    set { MyArray = value as IList<Class2>; } 
} 

To serializacji cokolwiek lista może być używany jako obiektu ogólnego z atrybutem type, który powie Deserializator rzeczywista typ obiektu, więc gdy ten obiekt zostanie przekształcony w deserializację, należy go ponownie rzucić na numer IList<Class2>. Pamiętaj, aby podać wszelkie typy, które mogą być zakładane przez interfejs.


Nie widzę powodu, dla którego żaden serializator nie mógłby być w stanie szeregować takich właściwości. To nie jest tak, że próbujesz serializować interfejs, próbujesz serializować obiekt, który implementuje pewien interfejs (który nie różni się zbytnio od abstrakcyjnej podklasy, niektóre języki programowania działają wyłącznie na interfejsach).

Kiedy serialalizator powinien serializować ten obiekt , wie, że obiekt implementuje ten interfejs, wszystko, co naprawdę trzeba zrobić, to przekształcić go do postaci szeregowej i dołączyć atrybut type (tak, jak robi to, jeśli serializuje się klasy abstrakcyjne lub tylko super-klasy ogólnie).

Teraz deserializator sprawdza typ i może sprawdzić, czy ten obiekt faktycznie implementuje wymagany interfejs, a następnie przekształca go w odpowiednią właściwość.

+0

Amen. Serializator jest głupi, jeśli chodzi o to! Dzięki za obejście. Znacznie lepiej jest używać interfejsów, ponieważ dziedziczenie jest ograniczone do jednej klasy bazowej. – toddmo

8

Zamiast tego należy użyć DataContractSerializer.

+1

To jest rzeczywiście poprawna odpowiedź. http://blogs.msdn.com/b/sowmy/archive/2008/10/04/serializing-internal-types-using-xmlserializer.aspx – l33t