Стратегия XmlSerialisation с интерфейсом?

У меня есть интерфейс, который на данный момент реализуют два класса. Данные для этих классов считываются из файла xml.

e.g.

[Serializable]
public interface IMyInterface { }

[Serializable]
public class MyClass1 : IMyInterface { }

[Serializable]
public class MyClass2 : IMyInterface { }

Я хочу вывести тип из Xml, есть ли способ сделать это?

Так, например, мой xml выглядит так:

 <meta type="MyClass1">
   <!--- Some meta data -->
 </meta>  

Я хочу иметь возможность напрямую сериализовать XML в объекты. В настоящее время я вручную обрабатываю xml.

Изменить: чтобы уточнить, я знаю, как сериализовать, но я не могу сериализовать обратно, не зная, какой тип он первый. Должен ли я прочитать атрибут типа, а затем сериализовать на его основе?


person Rob Stevenson-Leggett    schedule 16.03.2009    source источник


Ответы (4)


Если вы используете XmlSerializer, вы можете добавить атрибут XmlIncludeAttribute, чтобы указать производные классы, которые можно десериализовать. Но дело в том, что вы должны добавить его в класс base:

[XmlInclude(typeof(DerivedClass))]
public abstract class BaseClass
{
    public abstract bool Property { get; set; }
}

public class DerivedClass : BaseClass
{
    public override bool Property { get; set; }
}

Другим способом было бы реализовать IXmlSerializable для члена, который может быть получен, а затем иметь фабрику для производных классов на основе атрибута (или это то, что вы делаете прямо сейчас?)

person Groo    schedule 16.03.2009
comment
Это то, что я делаю сейчас, я подумаю о переходе на базовый класс. В любом случае это может иметь смысл. Спасибо. - person Rob Stevenson-Leggett; 16.03.2009

Сериализатор XML не предназначен для таких ситуаций. Он предназначен для сериализации объектов, которые могут быть отображены в XML, описанном схемой XML.

С другой стороны, сериализация во время выполнения включает средство форматирования SOAP, которое может сериализовать объекты, включая сведения об их типах .NET. Так может NetDataContractSerializer в WCF.

person John Saunders    schedule 16.03.2009

Если я правильно понял ваш запрос...

Имейте свойство в своем интерфейсе, скажем

[Serializable]
public interface IMyInterface 
{ 
 YourClassDifferentiatorEnum ObjectDifferentiator { get;  set; }
}

И пусть каждый класс устанавливает это значение с отдельным значением перечисления. Сериализуйте этот конкретный класс в XML.

Если вы хотите десериализовать (XML обратно в конкретный объект), затем десериализуйте его в IMyInterface, проверьте дифференциатор объекта и выполните соответствующее преобразование.

person 123Developer    schedule 16.03.2009

Не знаю, поможет ли это, но вот...

Что, если вы поместите общедоступное свойство в классы, которые возвращают имя типа

[XmlAttribute]
public string Type {
    get { return GetType().Name; }
}
person Jhonny D. Cano -Leftware-    schedule 16.03.2009