Как реализовать серию 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].
Ответ 3
Итак, вы уже внедрили сериализацию классов, насколько я могу видеть из вашего кода? Если вы пытаетесь вернуть объекты из ваших XML файлов, используйте десериализатор:
System.Xml.Serialization.XmlSerializer.Deserialize
Если бы вы не помнили, вы всегда можете генерировать код из схемы XML