Я работаю над внутренним проектом для моей компании, и часть проекта должна быть в состоянии проанализировать различные «Задачи» из файла 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 случаев в реальном коде) переключатель, чтобы выбрать, какой дочерний класс нужно создать. Я надеюсь, что есть какой-то полиморфный трюк, который я могу сделать здесь, чтобы очистить этот метод.
Любой совет?