Сериализация списка содержит интерфейс для XML

2

Я читал, но я не нашел решения моей проблемы

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

Мой объект содержит список Actions (List...), но есть 2 типа действия (пока). У меня есть действия типа SimpleAction и CompositeAction, и они оба наследуют от IAction, позволяя им быть оба в списке Actions.

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

Как, с некоторым примером кода, я пишу класс или сериализатор, который получает этот тип объекта и выполняет сериализацию объекта с правильным типом?

Некоторые коды:

  [XmlArray("Actions")]
  public List<IAction> Actions { get; set; }

  public interface IAction
   {
     int ID { get; set; }

     ParameterCollection Parameters { get; set; }

     List<SectionEntity> Validation { get; set; }

     TestResultEntity Result { get; set; }

     string Exception { get; set; }
   }

[XmlType("A")]
public class SimpleActionEntity : IAction
{
    #region IAction Members

    [XmlAttribute("ID")]
    public int ID { get; set; }

    [XmlIgnore]
    public ParameterCollection Parameters { get; set; }

    [XmlIgnore]
    public List<SectionEntity> Validation { get; set; }

    [XmlIgnore]
    public TestResultEntity Result { get; set; }

    [XmlElement("Exception")]
    public string Exception { get; set; }

    #endregion
}

Любая помощь будет принята с благодарностью.:)

Теги:
serialization

3 ответа

2
Лучший ответ

Хорошо, я создал решение, которое, как я чувствую, делает то, что мне очень нравится.

То, что я сделал, а не проведение

 [XmlArray("Actions")]
 public List<IAction> Actions { get; set; }

Я решил создать класс ActionsCollection, который обрабатывал List BUT, также позволял мне использовать IXMLSerializable для переопределения методов ReadXml и WriteXML, чтобы я мог обрабатывать способ сериализации и десериализации списка.

[XmlElement("Actions")]
public ActionCollection Actions { get; set; }

public class ActionCollection: CollectionBase, IXmlSerializable
{
    #region IList Members
      ...
    #endregion

    #region ICollection Members
     ...
    #endregion

    #region IEnumerable Members
    ...
    #endregion

    #region IXmlSerializable Members

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
       //TODO
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        foreach (IAction oAction in List)
        {       
                XmlSerializer s = new XmlSerializer(oAction.GetType());
                s.Serialize(writer, oAction);
        }
    }

    #endregion
}
  • 0
    Хороший. Я думаю, что установка [XmlInclude ("SimpleAction")] [XmlInclude ("ComplexAction")] также сработала бы.
3

Вы можете использовать XmlArrayItemAttribute, поскольку мы не обсуждали его, чтобы создать список IAction, поэтому полезно создавать базовый класс

public interface IAction {}
public abstract class ActionBase : IAction {}
public class SimpleAction : ActionBase {}
public class ComplexAction : ActionBase {}


[XmlArray("Actions")]
[XmlArrayItem(typeof(SimpleAction)),XmlArrayItem(typeof(ComplexAction))]
public List<ActionBase> Actions { get; set; }

Фактически вы также можете управлять именами элементов в XML файле следующим образом:

  [XmlArray("Actions")]
  [XmlArrayItem(typeof(SimpleAction),ElementName = "A")]
  [XmlArrayItem(typeof(ComplexAction),ElementName = "B")]
  public List<ActionBase> Actions { get; set; }
  • 1
    Когда я проектировал структуру объекта, я думал, что вы могли бы сделать это, но когда я пытаюсь сериализоваться, я получаю внутреннее исключение, говорящее, что я не могу сериализовать интерфейс.
  • 0
    Вы можете перепроектировать объектную модель, чтобы использовать абстрактный класс, который реализует интерфейс IAction, а затем наследовать все классы Action от абстрактного класса.
Показать ещё 2 комментария
0

Может быть, если вы получите два класса действий из общего абстрактного базового класса, который реализует интерфейс?

public interface IAction {}
public abstract class ActionBase : IAction {}
public class SimpleAction : ActionBase {}
public class ComplexAction : ActionBase {}

Затем вместо List<IAction> используйте List<ActionBase>.

  • 0
    Я также пробовал это, но, возможно, я реализовал это неправильно, потому что, когда сериализатор к списку, он только сериализует базовый класс, и это поведение бесполезно, так как в ComplexAction есть ряд дополнительных свойств
  • 0
    а что если SimpleAction наследует от другого базового класса? и не может наследовать от другого базового класса.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню