1

我想在 C# (.Net 4.0) 中创建一个 winform 应用程序,它使用文件对话框获取 xml 配置文件名。我是设计模式的新手,想在这个小应用程序中使用它。我已经阅读了很多关于各种设计模式的示例,但不知道该使用什么。这是此应用程序的说明。

此应用程序将运行各种作业。XML 配置文件可能包含多个作业。每个作业包含多个任务。任务可以是 1) 运行 SQL 查询 2) 搜索文本文件等,我计划在未来添加更多任务,例如检查文件是否存在。每个任务都有共同的属性,如名称、描述、启用。每个任务还​​具有特定于其自身的设置。例如,“运行 SQL 查询”任务包含 XML 中的连接字符串、查询和查询参数,而“搜索文本文件”任务包含文件列表和要搜索的文本。所以我生成的 XML 配置文件看起来像这样

<root>
  <jobs>
    <job>
      <name>My first job</name>
      <description>my first job log description</description>
      <tasks>
        <task>
          <name>Get employee</name>
          <description>gets a list of all employees</description>
          <type>SQLTask</type>
          <enabled>true</enabled>
          <settings>
            <connectionstring>myconnectionstring</connectionstring>
            <query>GetAllEmployees</query>
            <params>
              <param name="Dept">HR</param>
              <param name="EmpType">Permanent</param>
            </params>
          </settings>
        </task>
        <task>
          <name>Search process log</name>
          <description>searches process log for ERROR</description>
          <type>FileSearchTask</type>
          <enabled>true</enabled>
          <settings>
            <files>
              <file>c:\process\*.log</file>
              <file>c:\event\*.log</file>
            </files>
            <searchtoken>ERROR</searchtoken>
          </settings>
        </task>
      </tasks>
    </job>
    <job>ANOTHER JOB ...
    <job>
  </jobs>
</root>

此应用程序还负责创建 XML 文件。所以我应该能够以某种方式将对象保存为 XML 文件格式。

我能想到的简单方法是创建一个名为 Task 的抽象类,构造函数以 XML 作为参数。使用 TaskFactory.GetInstance(XMLDocument) 创建一个具体对象。在 SQLTask 和 SearchTextFileTask(从 Task 对象派生的具体对象)的构造函数中,它反序列化包括设置的对象(每个任务类型将有自己的设置对象)。如果我想用例如数据库存储替换 XML,这种设计的问题将是什么。我不确定我的想法是否正确。如果有人可以提供包含所有必要类/接口的存根代码,我将不胜感激。

4

1 回答 1

0

最近我为 c# 和远程 Web 服务器之间的数据库同步做了类似的事情。我的方法是使用 XML [反] 序列化和 C# 的反射命名空间从 XML 动态创建“未知”类。

我在下面提供了此代码的一些示例。不幸的是,我不认为这正是你所需要的,但希望它能给你一些想法,如果没有别的:

注意:我创建了一个名为 iSyncable 的接口,为可能需要同步的任何类提供一些“基本规则”——这也很重要,因为同步例程检查实现此接口的类,以决定发送什么(例如if (typeof(iSyncable).IsAssignableFrom(type)))。

下面遍历类“Hook.MySql”,搜索其类为“iSyncable”的任何成员,以确定它是否应序列化为 XML。如果找到,反射用于动态创建成员/类的副本(dynamic cls = Activator.CreateInstance(type, Hook.MySql);):

MemberInfo[] members = Hook.MySql.GetType().GetMembers();
foreach (MemberInfo member in members)
{
    if (member.MemberType == MemberTypes.Field) {
        fi = (FieldInfo)member;
        type = (fi).FieldType;
        if (typeof(iSyncable).IsAssignableFrom(type))
        {
            dynamic cls = Activator.CreateInstance(type, Hook.MySql);
            MemberInfo[] members2 = type.GetMembers();
            type2 = null;
            foreach (MemberInfo member2 in members2)
            {
                if (member2.Name == "Items")
                {
                    pi = (PropertyInfo)member2;
                    type2 = pi.PropertyType;
                    break;
                }
            }
            if (type2 != null)
            {
                XML = clsXml.Serialize(fi.GetValue(Hook.MySql), cls.XMLParent, type2);
            }
        }
    }
}

显然,这在某种程度上是为我的项目量身定制的,但是使用了许多有用的技术,这些技术应该可以转移。

这是我将上面创建的对象序列化为 XML 的 C# 代码:

public static string Serialize(dynamic o, string rootAttr, bool OmitXmlDeclaration = false, Type typeType = null)
{
    if (typeType == null) typeType = o.GetType();
    StringBuilder sb = new StringBuilder();
    XmlWriterSettings xws = new XmlWriterSettings();
    xws.OmitXmlDeclaration = OmitXmlDeclaration;
    using (XmlWriter writer = XmlWriter.Create(sb, xws))
    {
        try
        {
            new XmlSerializer(o.GetType(), null, new Type[] { typeType }, new XmlRootAttribute(rootAttr), "").Serialize(writer, o);
            //new XmlSerializer(o.GetType(), new XmlRootAttribute(rootAttr)).Serialize(writer, o);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
            Console.WriteLine(e.InnerException);
            Console.WriteLine(e.StackTrace);
        }
    }
    return fstr;
}

我希望这会有所帮助。需要帮助请叫我。

于 2013-06-15T01:06:57.523 回答