Почему XmlSerializer сериализует абстрактные классы, но не интерфейсы? - PullRequest
11 голосов
/ 13 января 2012

Редактировать Этот код должен иллюстрировать всю проблему:

[XmlInclude(typeof(AThing1))]
public abstract class AThing
{
    public abstract string Name { get; set; }
}

[XmlInclude(typeof(IThing1))]
public interface IThing
{
    string Name { get; set; }
}

public class AThing1 : AThing
{
    public override string Name { get; set; }
}

public class IThing1 : IThing
{
    public string Name { get; set; }
}

List<AThing> aThings = new List<AThing>(new AThing[] { new AThing1() { Name = "Bob" } });
List<IThing> iThings = new List<IThing>(new IThing[] { new IThing1() { Name = "Bob" } });

public void Test()
{
    using (StringWriter sw = new StringWriter())
    {
        XmlSerializer aSerializer = new XmlSerializer(typeof(List<AThing>));
        aSerializer.Serialize(sw, aThings);
        string text = sw.ToString();
    }

    using (StringWriter sw = new StringWriter())
    {
        // This line will throw "Cannot serialize interface IThing.":
        XmlSerializer iSerializer = new XmlSerializer(typeof(List<IThing>));    
        iSerializer.Serialize(sw, iThings);
        string text = sw.ToString();
    }
}

Первый text, сгенерированный aSerializer, будет:

<?xml version="1.0" encoding="utf-16"?>
<ArrayOfAThing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <AThing xsi:type="AThing1">
    <Name>Bob</Name>
  </AThing>
</ArrayOfAThing>

Я не понимаю, почему iSerializer не может сделать это:

<?xml version="1.0" encoding="utf-16"?>
<ArrayOfIThing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <IThing xsi:type="IThing1">
    <Name>Bob</Name>
  </IThing>
</ArrayOfIThing>

вместо исключения.

Ответы [ 2 ]

5 голосов
/ 13 января 2012

вы можете сериализовать интерфейс, но не так просто, как классы:

http://ventspace.wordpress.com/2010/02/20/how-to-serialize-interfaces-in-net/

, но чтобы ответить на ваш вопрос, у меня есть 2 предположения по этому поводу:

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

Если вы сериализуете полный объект вместе с информацией о типе, то сериализация интерфейса действительно ничего вам не даст.Вы могли бы напечатать ссылку как тип класса, во-первых, если ваше приложение действительно заботится о том, какой там объект.

Второй вариант соответствует заявленной цели XmlSerializer.Несмотря на вводящее в заблуждение название, XML Serialization в .NET Framework действительно является технологией привязки данных, основной целью которой является сопоставление типов данных MXL, определенных в схемах XSD, с типами .NET.Определение XSD знает об абстрактных базовых классах, но, поскольку оно ориентировано на данные, ничего не знает об интерфейсах.Имея это в виду, мало мотивации для поддержки интерфейсов в XmlSerializer.

2 голосов
/ 13 января 2012

XmlSerializer не сериализует абстрактные классы. Он сериализует один из нескольких конкретных классов.

...