2011-01-11 4 views
9

Я пытаюсь запустить код, подобный этому:Сериализация интерфейсы

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

Может кто-нибудь объяснить мне, что я делаю неправильно?

я получаю:

Не могу сериализовать член .. MyArray ... потому что это интерфейс.

Не следует ли разрешить XmlInclude?

+0

Кто бы ни говорил о десериализации ...? –

ответ

13

№ Вы не можете сериализовать интерфейс. Когда-либо. Он просто сказал вам об этом.

Интерфейс - это не что иное, как описание набора поведений. Он ничего не говорит о содержимом экземпляра. В частности, хотя экземпляр класса, реализующего интерфейс, должен реализовывать все его члены, он, несомненно, будет иметь свои собственные свойства, которые должны быть сериализованы.

Как его десеризировать?

Какой класс будет использоваться для десериализации интерфейса с другой стороны?

+0

Любые обходные пути? – Shahar

+3

@Shahar: да. Не делай этого. Используйте конкретный тип, а не интерфейс. –

+1

Как его десериализировать? Как экземпляр класса, который был сериализован, точно так же, как List . Какой класс будет использоваться для десериализации интерфейса с другой стороны? См. Первый ответ. – jwg

0

Вы включили typeof (Список < ...>), но MyArray имеет тип IList < ...>, который не является самой явной структурой данных, а скорее заполнителем, чтобы взять некоторую структуру данных.

Измените тип MyArray на определенный тип (например, List), и он должен работать.

private List<Class2> myArray; 

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

Вот непроверенный теневой обходной путь, что я, как правило, использую в принципе:

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

Это будет сериализовать любой список, вы можете использовать в качестве родового объекта с атрибутом типа, который сообщит десериализатору фактический тип объекта, поэтому, когда этот объект будет десериализован, он должен быть снова добавлен в IList<Class2>. Не забудьте указать любые типы, которые могут быть приняты интерфейсом.


Я не вижу причин, почему какой-либо сериализатор не может сериализовать такие свойства. Это не так, как вы на самом деле пытаетесь сериализовать интерфейс, вы пытаетесь сериализовать объект, который реализует определенный интерфейс (который не сильно отличается от абстрактного подкласса, некоторые языки программирования даже работают исключительно на интерфейсах).

Когда сериализатор должен сериализовать этот объект он знает, что объект реализует этот интерфейс, все это действительно нужно сделать, это сериализовать его и прикрепить атрибут типа (как это делает, если вы сериализацию абстрактные классов или просто супер-классов в целом).

Теперь десериализатор смотрит на тип, и может проверить, если этот объект фактически реализует необходимый интерфейс и затем десериализует его в соответствующее свойство.

+0

Аминь. Сериализатор глуп, когда дело доходит до этого! Спасибо за обход. Гораздо лучше использовать интерфейсы, потому что наследование ограничено одним базовым классом. – toddmo

8

Или используйте вместо этого DataContractSerializer.

+1

Это действительно правильный ответ. http://blogs.msdn.com/b/sowmy/archive/2008/10/04/serializing-internal-types-using-xmlserializer.aspx – l33t