【问题标题】:Where to store configuration information存储配置信息的位置
【发布时间】:2009-02-23 14:24:13
【问题描述】:

我有一个控制台应用程序,我正在从 C 重建到 C#。此应用程序必须能够支持存储信息的传统方法,例如来自命令行的参数和来自文件的参数(称为系统参数),用于自定义每次运行。系统参数文件是纯文本格式,具有简单的键值结构。

我的问题是:

  • 我应该将这些不同的参数组合成一个配置对象吗?
  • 如何从代码中调用此配置对象来存储参数?
  • 如何从代码中调用此配置对象来检索参数?
    • 这个对象应该是强类型的吗?
  • 我需要从代码中的许多不同位置访问这个结构。在不到处传递对象本身的情况下检索对象中的值的最优雅方法是什么?

我有一种感觉,它应该是一个单一的强类型对象,并且它应该是一个实例化的对象,该对象是通过静态检索方法从存储库中检索出来的,但是我真的想要验证这个方法。

【问题讨论】:

    标签: c# .net configuration


    【解决方案1】:

    我会使用如下的单个配置对象:

    using System;
    using System.IO;
    using System.Reflection;
    public sealed class Setting {
      public static int FrameMax { get; set; }
      public static string VideoDir { get; set; }
      static readonly string SETTINGS = "Settings.ini";
      static readonly Setting instance = new Setting();
      Setting() {}
      static Setting() {
        string property = "";
        string[] settings = File.ReadAllLines(SETTINGS);
        foreach (string s in settings)
          try {
            string[] split = s.Split(new char[] { ':' }, 2);
            if (split.Length != 2)
              continue;
            property = split[0].Trim();
            string value = split[1].Trim();
            PropertyInfo propInfo = instance.GetType().GetProperty(property);
            switch (propInfo.PropertyType.Name) {
              case "Int32":
                propInfo.SetValue(null, Convert.ToInt32(value), null);
                break;
              case "String":
                propInfo.SetValue(null, value, null);
                break;
            }
          } catch {
            throw new Exception("Invalid setting '" + property + "'");
          }
      }
    }
    

    因为这是一个singleton,所以当第一次从Setting 对象引用public static 属性时,它将创建一个且只有一个自身实例。

    创建对象时,它从Settings.ini 文件中读取。设置文件是一个纯文本文件,具有简单的key : value 结构,可能如下所示:

    FrameMax : 12
    VideoDir : C:\Videos\Best
    

    对象使用反射来发现每个属性并存储其初始值。在本例中,定义了两个属性:

        public static int FrameMax { get; set; }
        public static string VideoDir { get; set; }
    

    编写的代码处理Int32String 类型。通过在switch 语句中添加额外的case 语句,您可以轻松添加对FloatDecimal 等类型的支持。

    要更改设置,您可以使用以下内容:

    Setting.FrameMax = 5;
    

    要检索设置,您可以使用以下内容:

    if (Setting.FrameMax > 10) ...
    

    您会注意到所有属性都是强类型的。此外,您不必传递Setting 对象,因为所有Setting 属性都是static 并且始终可用。

    我希望这个想法会有所帮助。

    【讨论】:

    • 这似乎不会将设置更改保存到文件中...例如 Setting.MyValue = 19 不会将其保存到 Settings.ini 文件中。
    • 版本控制怎么样(最简单的情况是添加一个新的配置项)?如果使用由旧版本应用程序创建的配置文件,它会中断吗?
    【解决方案2】:

    我喜欢使用Settings。这些可以通过使用添加新文件对话框创建设置文件或通过从项目属性添加默认设置文件来自动生成。

    每个设置都可以在用户或应用程序范围内,它控制用户是否可以更改它们或将它们限制为默认值。它们可以使用Save() 方法轻松保存并自动加载到静态Default 属性中。

    这个类似乎是用于应用程序或基于用户的设置。我正在寻找每次运行的设置。在这种情况下,你还会推荐使用这个类吗? – x97mdr

    是的。如果您同时拥有基于用户/应用程序的设置和每次运行设置,您应该使用两个不同的类 - 正常(已保存)设置和每次运行设置。

    只要您不保存每次运行的设置,您应该是安全的,并且设置仍然很容易使用。这些是静态设置。如果同一个应用程序运行需要多个实例 - 这是错误的方法。

    【讨论】:

    • 这个类似乎是用于应用程序或基于用户的设置。我正在寻找每次运行的设置。在这种情况下,你还会推荐使用这个类吗?
    【解决方案3】:

    我发现每当我必须处理旧系统时,坚持旧格式几乎总是效果最好。很多时候,其他人使用旧格式执行其他任务(例如应用程序的自动化),因此如果您重新编码应用程序处理输入的方式,您可能会破坏其他系统。

    另一方面,如果您非常自信地了解所有使用该系统的人,并且他们告诉您他们不在乎您是否更改这些类型的内容,那么我可能会将所有内容都迁移到 XML。除了从应用程序的角度来看 XML 的所有不错的特性(比如以 ASCII 格式,因此很容易被人类修改、自我记录等......),XML 还可以节省时间,因为您没有编写自己的 I/O 或解析器。已经有各种各样的库,特别是在 .NET 3.0/3.5 中,它们都做得很好。 (当您转向 C# 时,我猜您已经在考虑这些方面了 :)

    因此,最终,您必须根据实施成本做出决定:如果您通过迁移到 XML 或类似方式来降低您的实施成本,请确保您不会提高其他人迁移到您的新应用程序框架的实施成本。

    祝你好运!

    【讨论】:

    • 我现在必须能够支持旧格式。不过,我想在将来转向 XML。您如何看待上述设置类?
    • 但是您如何处理版本控制?最简单的是添加一个新的配置设置。
    【解决方案4】:

    XmlDocument - 您可以使用XSD.exe 生成类定义

    【讨论】:

    • 但是您如何处理版本控制?最简单的是添加一个新的配置设置。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-26
    • 1970-01-01
    • 2021-04-01
    • 2020-03-17
    相关资源
    最近更新 更多