Я работаю над внутренним проектом для своей компании, и часть проекта состоит в том, чтобы анализировать различные "Задачи" из XML файла в коллекцию задач, которые будут запущены позже.
Поскольку каждый тип задачи имеет множество разных связанных полей, я решил, что лучше всего представлять каждый тип задачи с отдельным классом.
Для этого я построил абстрактный базовый класс:
public abstract class Task
{
public enum TaskType
{
// Types of Tasks
}
public abstract TaskType Type
{
get;
}
public abstract LoadFromXml(XmlElement task);
public abstract XmlElement CreateXml(XmlDocument currentDoc);
}
Каждая задача, унаследованная от этого базового класса, и включала код, необходимый для создания самого из переданного в XmlElement, а также сериализовать себя обратно в XmlElement.
Основной пример:
public class MergeTask : Task
{
public override TaskType Type
{
get { return TaskType.Merge; }
}
// Lots of Properties / Methods for this Task
public MergeTask (XmlElement elem)
{
this.LoadFromXml(elem);
}
public override LoadFromXml(XmlElement task)
{
// Populates this Task from the Xml.
}
public override XmlElement CreateXml(XmlDocument currentDoc)
{
// Serializes this class back to xml.
}
}
Затем синтаксический анализатор будет использовать код, подобный этому, для создания коллекции задач:
XmlNode taskNode = parent.SelectNode("tasks");
TaskFactory tf = new TaskFactory();
foreach (XmlNode task in taskNode.ChildNodes)
{
// Since XmlComments etc will show up
if (task is XmlElement)
{
tasks.Add(tf.CreateTask(task as XmlElement));
}
}
Все это прекрасно работает и позволяет мне выполнять задачи вокруг базового класса, сохраняя при этом структуру отдельных классов для каждой задачи.
Однако мне не нравится мой код для TaskFactory.CreateTask. Этот метод принимает XmlElement, а затем возвращает экземпляр соответствующего класса Task:
public Task CreateTask(XmlElement elem)
{
if (elem != null)
{
switch(elem.Name)
{
case "merge":
return new MergeTask(elem);
default:
throw new ArgumentException("Invalid Task");
}
}
}
Поскольку мне приходится разбирать XMLElement, я использую огромный (10-15 случаев в реальном коде) переключатель, чтобы выбрать, какой дочерний класс нужно создать. Я надеюсь, что есть какой-то полиморфный трюк, который я могу сделать для очистки этого метода.
Любые советы?