使用XML构建的对象的C#设计模式

时间:2013-06-15 00:39:44

标签: c# xml design-patterns

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

此应用程序将运行各种作业。 XML配置文件可能包含多个作业。每个作业包含多个任务。任务可以是1)运行SQL查询2)搜索文本文件等,我计划在将来添加更多任务,如检查文件的存在。每个任务都有公共属性,如Name,Description,Enabled。每个任务还​​具有特定于自己的设置。例如,“运行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,那么这种设计的问题就是这样。我不确定我是否正在朝着正确的方向思考。如果有人可以提供包含所有必要类/接口的存根代码,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

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

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

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

以下迭代“Hook.MySql”类,搜索其类为“iSyncable”的任何成员,以决定是否应该序列化为XML。如果找到,则使用Reflection来动态创建成员/类的副本(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);
            }
        }
    }
}

显然,这是根据我的项目量身定制的,但是有许多有用的技术应该可以转让。

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

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;
}

我希望这会有所帮助。如果您还有其他需要,请告诉我。