I'm working on an internal project for my company, and part of the project is to be able to parse various "Tasks" from an XML file into a collection of tasks to be ran later.
Because each type of Task has a multitude of different associated fields, I decided it would be best to represent each type of Task with a seperate class.
To do this, I constructed an abstract base class:
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);
}
Each task inherited from this base class, and included the code necessary to create itself from the passed in XmlElement, as well as serialize itself back out to an XmlElement.
A basic example:
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.
}
}
The parser would then use code similar to this to create a task collection:
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));
}
}
All of this works wonderfully, and allows me to pass tasks around using the base class, while retaining the structure of having individual classes for each task.
However, I am not happy with my code for TaskFactory.CreateTask. This method accepts an XmlElement, and then returns an instance of the appropriate Task class:
public Task CreateTask(XmlElement elem)
{
if (elem != null)
{
switch(elem.Name)
{
case "merge":
return new MergeTask(elem);
default:
throw new ArgumentException("Invalid Task");
}
}
}
Because I have to parse the XMLElement, I'm using a huge (10-15 cases in the real code) switch to pick which child class to instantiate. I'm hoping there is some sort of polymorphic trick I can do here to clean up this method.
Any advice?