Как реализовать серию Xml с унаследованными классами в С#

У меня есть два класса: имя базового класса. Компонент и класс inheritd с именем DBComponent

[Serializable]
public class Component
{
    private string name = string.Empty;
    private string description = string.Empty;  
}

[Serializable]
public class DBComponent : Component
{
    private List<string> spFiles = new List<string>();

    // Storage Procedure Files
    [XmlArrayItem("SPFile", typeof(string))]
    [XmlArray("SPFiles")]
    public List<string> SPFiles
    {
        get { return spFiles; }
        set { spFiles = value; }
    }

    public DBComponent(string name, string description)
        : base(name, description)
    { }
}  

[Serializable]
public class ComponentsCollection
{
  private static ComponentsCollection instance = null;
  private List<Component> components = new List<Component>();

  public List<Component> Components
  {
      get { return components; }
      set 
      { 
            components = value; 
      }
  }

   public static ComponentsCollection GetInstance()
    {
        if (ccuInstance == null)
        {
            lock (lockObject)
            {
                if (instance == null)
                    PopulateComponents();
            }
        }
        return instance;
    }

    private static void PopulateComponents()
    {
        instance = new CCUniverse();
        XmlSerializer xs = new XmlSerializer(instance.GetType());
        instance = xs.Deserialize(XmlReader.Create("Components.xml")) as ComponentsCollection;
    }
}

}

Я хочу читать\писать из Xml файла. Я знаю, что мне нужно реализовать сериализацию для класса DBComponent, иначе он не будет читать его. Но я не могу найти для этого какую-либо простую статью. все статьи, которые я нашел, были слишком сложными для этого простого сценария.
Файл Xml выглядит следующим образом:

<?xml version="1.0" encoding="utf-8" ?>
  <ComponentsCollection>    
    <Components>
            <DBComponent Name="Tenant Historical Database" Description="Tenant Historical Database">
                    <SPFiles>
                        <SPFile>Setup\TenantHistoricalSP.sql</SPFile>
                    </SPFiles>
            </DBComponent>
            <Component Name="Agent" Description="Desktop Agent" />
        </Components>  
  </ComponentsCollection>

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

Спасибо
Лиор

Ответ 1

К сожалению, вам нужно указать XmlSerializer классы, которые вы собираетесь сериализовать или десериализовать, используя атрибут XmlArrayItem(). Каждому разному типу также требуется собственное имя элемента. Например:

public class ComponentDerviedClass1: Component
public class ComponentDerivedClass2: Component
public class ComponentDerivedClass3: Component

// ...

public class ComponentsCollection
{
    [XmlArray("Components")]
    [XmlArrayItem("ComponentDerivedClass1", typeof(ComponentDerivedClass1))]
    [XmlArrayItem("ComponentDerivedClass2", typeof(ComponentDerivedClass2))]
    [XmlArrayItem("ComponentDerivedClass3", typeof(ComponentDerivedClass3))]
    public List<Component> Components
    {
        // ...
    }
}

Это будет читать XML файл, например:

<?xml version="1.0" encoding="utf-8" ?>
<ComponentsCollection>    
  <Components>
     <ComponentDerivedClass1>
         <!-- ... -->
     </ComponentDerivedClass1>
     <ComponentDerivedClass2>
         <!-- ... -->
     </ComponentDerivedClass2>
     <ComponentDerivedClass3>
         <!-- ... -->
     </ComponentDerivedClass3>
   </Components>  
</ComponentsCollection>

Несколько экземпляров каждого элемента могут присутствовать (или нет).

Ответ 2

Два варианта для разных сцен: укажите базовый класс

[XmlInclude(typeof(DBComponent))]
public class Component
{
    private string name = string.Empty;
    private string description = string.Empty;  
}

Или: скажите коллекции:

[XmlArray]
[XmlArrayItem("Component", typeof(Component))]
[XmlArrayItem("DBComponent", typeof(DBComponent))]
public List<Component> Components {...}

Собственно, вы также можете использовать [XmlElement (...)] вместо [XmlArrayItem], если вы не хотите внешний node (Components). Также: вам не нужно [Serializable].