私は会社の内部プロジェクトに取り組んでおり、プロジェクトの一部は、XML ファイルからさまざまな「タスク」を解析して、後で実行するタスクのコレクションにできるようにすることです。
Task の各タイプには多数の異なる関連フィールドがあるため、Task の各タイプを個別のクラスで表すのが最善であると判断しました。
これを行うために、抽象基本クラスを構築しました。
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 ケース) スイッチを使用しています。このメソッドをクリーンアップするために、ここで実行できる何らかのポリモーフィック トリックがあることを願っています。
何かアドバイス?