C# 在哪里存储配置信息

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/577782/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 09:00:28  来源:igfitidea点击:

Where to store configuration information

c#.netconfiguration

提问by Jeffrey Cameron

I have a console application that I am rebuilding from C to C#. This application has to be able to support the legacy method of storing information like parameters from a command-line and parameters from a file (called the system parameters) that customize each run. The system parameters file is in plain-text with a simple key-value structure.

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

My questions are:

我的问题是:

  • Should I combine these different parameters into a single Configuration object?
  • How would I call this configuration object from the code to store parameters?
  • How would I call this configuration object from the code to retrieve parameters?
    • Should this object be strongly-typed?
  • I will need access to this structure from a lot of different places in the code. What is the most elegant way to retrieve the values in the object without passing the object itself around everywhere?
  • 我应该将这些不同的参数组合成一个配置对象吗?
  • 我如何从代码中调用这个配置对象来存储参数?
  • 我如何从代码中调用这个配置对象来检索参数?
    • 这个对象应该是强类型的吗?
  • 我需要从代码中的许多不同地方访问这个结构。在不到处传递对象本身的情况下检索对象中的值的最优雅的方法是什么?

I have a feeling that it should be a single, strongly-typed object and that it should be an instantiated object that is retrieved from a repository with a static retrieval method however I really want validation of this method.

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

采纳答案by configurator

I like using Settings. These can be generated automatically either by creating a settings file using the Add New Filedialog box, or by adding a default settings file from project properties.

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

Each setting may be in user or application scope, which controls whether or not the user can change them or they are restricted to their default values. They are easily saved with the Save()method and loaded automatically into the static Defaultproperty.

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

This class seems to be for application or user-based settings. I'm looking for per-run settings. Would you still recommend using this class in that case? – x97mdr

此类似乎用于应用程序或基于用户的设置。我正在寻找每次运行设置。在这种情况下,您是否仍建议使用此类?– x97mdr

Yes. If you have both user/application based settings and per-run settings you should use two different classes - the normal (saved) settings and the per-run settings.

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

As long as you don't save the per-run settings, you should be safe and settings are still quite easy to use. These are static settings though. If the same application run needs several instances - this is the wrong approach.

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

回答by Jason

XmlDocument - you can generate a class definition using XSD.exe

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

回答by Mike

I find that whenever I have to deal with a legacy system, sticking with the old format almost always works best. Often times there are other people using the legacy formats for other tasks (like automation of the app, for example), so if you recode the way the application handles inputs, you might break other systems.

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

On the other hand, if you are pretty confident that you know all the people using the system, and they tell you that they don't care if you change these types of things, I would probably move everything to XML. Besides all the nice features of XML from an application point of view (like being in ASCII so it's easily modified by humans, being self-documenting, etc ...), XML is also time-saving, in that you don't have to write your own I/O or parser. There's already a wide variety of libraries out there, particularly in .NET 3.0/3.5, that do very well. (As you're moving to C#, I'm guessing you're already thinking along these lines :)

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

So ultimately, you'd have to base your decision on cost-to-implement: if you lower yourcost of implementation by moving to XML or similar, make sure that you don't raise other people'scost of implementation to move to your new application framework.

所以,最后,你必须立足于成本对实现你的决定:如果你降低你的移动,以XML或类似的实施成本,确保不提高其他人的实现成本转移到新应用程序框架。

Good luck!

祝你好运!

回答by Protagonist

I would use a single configuration object like the following:

我将使用如下所示的单个配置对象:

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 + "'");
      }
  }
}

Since this is a singleton, it will create one and only one instance of itself the first time a public staticproperty is referenced from the Settingobject.

由于这是一个单例,它会在第一次public staticSetting对象中引用属性时创建一个并且只有一个它自己的实例。

When the object is created, it reads from the Settings.inifile. The settings file is a plain-text file with a simple key : valuestructure that might look like this:

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

FrameMax : 12
VideoDir : C:\Videos\Best

The object uses reflection to discover each property and to store its initial value. In this example, two properties have been defined:

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

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

The code as written handles Int32and Stringtypes. By adding additional casestatements to the switchstatement, you could easily add support for types like Floatand Decimal.

代码作为书面句柄Int32String类型。通过添加额外的case语句来的switch声明中,你可以轻松地添加支持的类型喜欢FloatDecimal

To change a setting, you would use something like:

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

Setting.FrameMax = 5;

To retrieve a setting, you would use something like:

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

if (Setting.FrameMax > 10) ...

You'll notice that all the properties are strongly-typed. Also, you don't have to pass the Settingobject around, as all the Settingproperties are staticand always available everywhere.

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

I hope this idea is helpful.

我希望这个想法有帮助。