首页 > 解决方案 > 通过解析 xml 文件 (app.config) 读取应用程序设置的优雅解决方案

问题描述

我正在使用 xml 阅读器通过一个单独的项目读取 app.config 设置。其他 dll 中的 Properties.Settings.Default.MySetting 无法读取 app.config。现在我试图找到一个合适的解决方案,如何读取不同格式的不同设置(StringCollection,String,...)。

https://imgur.com/a/AxeCTsC

(对于所有问我为什么不像这样阅读 TestConsole 中的信息的人:

            var sc = Properties.Settings.Default.PathToPython;

那是因为我重用了这些项目。在这种情况下,我有一个 TestConsole,我将添加服务应用程序。TestConsole 应用程序仅用于开发。但我不想将我的代码从一个应用程序复制到另一个应用程序。TestConsol 或更高版本的服务应用程序获得尽可能少的代码。

app.config 的一部分如下所示:

<applicationSettings>
<ToolkitConnector.Ui.TestConsole.Properties.Settings>
  <setting name="PythonApp" serializeAs="String">
    <value>status.py</value>
  </setting>
  <setting name="PathToPython" serializeAs="String">
    <value>python</value>
  </setting>
  <setting name="OutputFolder" serializeAs="String">
    <value>c:\toolkit_1\status\statusOfPlatform1\</value>
  </setting>
  <setting name="PySkriptWorkingDirectory" serializeAs="String">
    <value>c:\toolkit_1\</value>
  </setting>
  <setting name="LgInInformation" serializeAs="Xml">
    <value>
      <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <string>User1</string>
        <string>Pwd1</string>
        <string>GER_PROD</string>
        <string>18701</string>
        <string>Technology1</string>
        <string>User2</string>
        <string>Pwd2</string>
        <string>GER_PROD</string>
        <string>18795</string>
        <string>Technology2</string>
      </ArrayOfString>
    </value>
  </setting>
</ToolkitConnector.Ui.TestConsole.Properties.Settings>

在我的项目 Logic.ControlAppSetting 中,我使用该代码来读取 xml 文件

        public void GetApplicationSetting(string path)
        {
            XmlDocument doc = new XmlDocument();
            try
            {
                doc.Load(path);
                XmlElement root = doc.DocumentElement;
                var applicationSettings = root.SelectSingleNode("applicationSettings");
                var mySettings = applicationSettings.SelectSingleNode("ToolkitConnector.Ui.TestConsole.Properties.Settings");
                foreach (XmlNode node in mySettings)
                {
                    var test = node.Attributes;
                }
            }
            catch { }
        }

现在我正在寻找一个优雅的解决方案来将设置信息存储在变量中。我的问题是我有不同的类型,如 StringCollection 和 String。可能有更好的方法来存储这些信息吗?

非常感谢

编辑:

我也尝试过:

Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
            ConfigurationSectionGroup userSettings = config.GetSectionGroup("applicationSettings");
            ClientSettingsSection settings = (ClientSettingsSection)userSettings.Sections.Get("Ui.TestConsole.Properties.Settings");
            SettingElement elem = settings.Settings.Get("LgInInformation");

标签: c#xml

解决方案


最简单的解决方案是不要让其他库直接依赖于该文件或Settings用于读取其值的自动生成的类。您的库不需要文件或类。它只需要价值观。

如果您的库依赖于读取此文件,那么它只能在存在该文件的环境中工作。这将使其难以使用。通常我们可以只添加对库的引用并使用它。但是如果库依赖于这个文件,那么我们将不得不修改使用该库的应用程序以包含这些设置。

这也将使为您的库编写单元测试变得困难或不可能。您还必须将所有这些设置添加到您的单元测试项目中。但是,如果您想使用两种不同的设置为库编写测试怎么办?那会很痛苦。

相反,定义一个与环境无关的类,它包含这个库需要的设置。

以最简单的形式,

public class MyLibraryConfigurationSettings
{
    public string PythonApp { get; set; }
    public List<string> LgInInformation { get; } = new List<string>();
}

然后编写您的库,以便调用应用程序必须提供这些设置才能使用它。

现在你已经完成了它的图书馆方面的工作。为了使用它,你必须给它它需要的东西。它不知道也不关心这些值从何而来。它不知道是否有配置文件或它在哪里。

现在您的应用程序必须将它提供给库。它可以通过创建该类的实例并使用Properties.Settings.Default.MySetting. 或者它可以以其他方式填充它。现在您的应用程序也不会被迫使用该文件。


这种方法的另一个好处是它使需求更加明确。例如,您可以创建您的库,以便将其添加到您的应用程序需要提供配置值。例如,许多库提供扩展以将自己注册到IServiceCollection. 你可以这样做:

services.AddYourLibrary(MyLibraryConfigurationSettings settings);

很明显,这是应用程序必须提供的。您可以通过提供一个可以轻松反序列化的类来简化它。

如果您依赖该文件,则该关系不太清楚。您可以添加对库的引用,编写一些代码,一切看起来都不错。然后在运行时它会抛出一个异常,说“文件在哪里?” 开发人员说,“什么文件?” 他们必须寻找准确描述该文件必须如何定义的文档。<applicationSettings>如果必须使用该部分创建文件,则将更加复杂。


推荐阅读