【发布时间】:2010-09-06 20:06:47
【问题描述】:
我正在为我的公司开展一个内部项目,该项目的一部分是能够将 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 例)开关来选择要实例化的子类。我希望我可以在这里做一些多态技巧来清理这个方法。
有什么建议吗?
【问题讨论】:
-
检查所有案例具有安全优势。 reflection answer 存在安全漏洞,有人将 Task 类(不是您创建的)注入您的路径并通过将其名称放入 XML 来执行它。黑客做了更难的事情。
标签: c# design-patterns factory