65.9K
CodeProject 正在变化。 阅读更多。
Home

自定义 AppSettings

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.12/5 (7投票s)

2005年11月29日

CPOL

5分钟阅读

viewsIcon

86240

downloadIcon

1898

又一篇关于 AppSettings 的文章。

引言

有很多文章讨论 .NET 应用程序的 App.config 文件,无论是控制台应用程序、WinForms 应用程序还是服务,不仅在 CodeProject 上,而且在互联网上随处可见。

它们看起来可能都差不多;但归根结底,没有一篇是完全相同的。这就是为什么我确信本文不会与其他您发现和阅读过的文章相同。谁知道呢,它可能会以某种方式帮助您,甚至更好的是,您可能会获得一些想法并对其进行改进。

我的情况就是如此,我一直在寻找一种自定义、通用的方法来读取我的 App.config,但没有一篇文章说服我,也没有解决我当时的需求,但它们确实给了我关于我想在自己的实现中做什么的好主意。

别人的想法

我从这个开源网站(当然我说的是 CodeProject)上借鉴了两个主要想法。

Paul Haley 在他的 “增强的 AppSettings 配置处理程序” 文章中写道,有时您需要在不同的环境中使用不同的配置来尝试您的应用程序,为此而编辑或注释代码可能会相当烦人。此外,App.config 文件是所有配置都应该存在的地方。(他解释了更多缺点。)

无论如何,他的方法有点更偏向于主机名,如果您想更改这一点,您必须继承他的类并做一些我没费心去读的其他事情。

Diego Mijelshon 有一篇关于 “如何使 AppSettings 与键的多个值一起工作” 的文章。现在,您必须同意我,这也很棒。他明确指出 .NET 有这个严重的缺陷,并且他大致解释了原因。他还展示了如何获取键的多个值,但我认为他使用反射(不是说反射很难)将事情复杂化了一点,原因我不得而知。

我必须指出,这两篇文章都没有问题,它们都能正常工作,但我的需求不同,所以我认为它们会太复杂,事实也确实如此。

背景

当然,建议您了解 appSettingsSystem.Configuration.ConfigurationSettings 类、App.config 文件以及编码该文件的 XML。这些主题相当容易,我猜大多数 [.NET] 程序员必须知道或至少听说过它们,对吧?

好了,说完了……我们开始吧!

主要思想

如您可能已经读到的,您可以使用 ConfigurationSettings.AppSettings[...] 获取 App.config 中的简单值,或者可以使用 ConfigurationSettings.GetConfig(string sectionName) 方法创建和读取自定义节,但如果您想自己读取配置文件,则必须创建一个实现 IConfigurationSectionHandler 接口的类,这很容易做到,例如

public class AppSettingHandler : IConfigurationSectionHandler

这样做会迫使您在类中实现一个方法,即 Create(...) 方法,该方法基本上将整个 App.config 文件作为名为 sectionXmlNode 提供给您。在该方法中,您可以按照您想要的任何方式读取值。

public virtual object Create(object parent, object configContext, XmlNode section)

使用和获取正确的代码

现在,为了让您的主代码自动调用您刚刚实现的 Create(...) 方法,您必须执行以下操作

首先,您的应用程序必须有一个有效且正确的 App.config XML 文件。在其中,您必须包含类似这样的内容,以便可以使用我提供的代码

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <configSections>
        <remove name="appSettings"/>
        <section name="appSettings" 
                type="BellAppSetting.AppSettingHandler, BellAppSetting" />
    </configSections>

    <appSettings>
        <!-- CONFIGURATION GOES HERE-->     
    </appSettings>
    
</configuration>

在继续之前,我想指出,没有必要删除 appSettings 节,这只是如果您想将配置放在 <appSettings> 标记内。您可以改为使用类似这样的内容

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <configSections>
        <section name="TheNameIwant" 
                  type="BellAppSetting.AppSettingHandler, BellAppSetting" />
    </configSections>
    
    <TheNameIwant>
        <!-- CONFIGURATION GOES HERE-->
    </TheNameIwant>

</configuration>

其次,您必须从主代码调用以下行

ArrayList nvc;
nvc = (ArrayList)ConfigurationSettings.GetConfig("appSettings");

如果您在 App.config 文件中使用了 <remove name="appSettings"/>,或者

ArrayList nvc;
nvc = (ArrayList)ConfigurationSettings.GetConfig("TheNameIwant");

如果您在 App.config 文件中使用了 <section name="TheNameIwant"

您获得的示例

从调用的代码行可以看出,您返回的是一个 ArrayList。它的结构将在以下示例中显示。如果您需要更多详细信息,请随时下载源代码。

假设您的 App.config 看起来像这样

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

    <configSections>
        <remove name="appSettings"/>
        <section name="appSettings" 
                    type="BellAppSetting.AppSettingHandler, BellAppSetting" />
    </configSections>
    
    <appSettings>

          <Configs use="true"> 
            <add key="ClientConfig" use="true" />
            <add key="ServerConfig" use="true"/> 
            <add key="OtherValue3" use="false"/> 
          </Configs>

          <Configs use="true"> 
            <add key="ClientConfig" use="true" />
            <add key="ServerConfig" use="true"/> 
            <add key="OtherValue3" use="true"/> 
            <add key="OtherValue4" use="true"/> 
          </Configs>
        
          <ClientConfig use="true">
            <add key="Address2Connect" value="192.168.1.107"/> 
            <add key="Port2Connect" value="2000"/> 
            <add key="Log2File" value="Logging.txt"/>          
          </ClientConfig>
          
          <ClientConfig use="true">
            <add key="Address2Connect" value="192.168.1.105"/> 
            <add key="Port2Connect" value="2000"/> 
          </ClientConfig>
              
          <ServerConfig use="true">
            <add key="PortListenerName" value="2002"/> 
            <add key="Port2Listen" value="2002"/> 
            <add key="PortLisFile2Log" value="Logging.txt"/>
          </ServerConfig>
          
          <ServerConfig use="false">
              <add key="PortListenerName" value="2004"/> 
            <add key="Port2Listen" value="2004"/> 
            <add key="PortLisFile2Log" value="Logging.txt"/>
            <add key="PortLisLogAll2File" value="false"/>
            <add key="GossipSockets" value ="false"/>
            <add key="SocketLogAll2IndependantFile" value="false"/>
         </ServerConfig>
         
          <OtherValue4 use="true"> 
            <add key="CheckConnections" value="false"/> 
            <add key="NotifyUserWhenDone" value="true"/> 
            <add key="OtherConfigValue" value="1"/> 
            <add key="OtherConfigValue" value="2"/> 
          </OtherValue4>
         
    </appSettings>
    
</configuration>

如果您使用示例项目处理此 App.config,您将得到类似这样的结果

最后一些说明

  • <Configs> 节点用作节集合。
  • 您可以根据需要放置任意数量的 <Configs> 节点。
  • 您可以根据需要放置任意数量的元素节点。
  • 您可以看到所有节点都有一个 use 属性,该属性可以接受 truefalse,告诉代码是否要跳过它。
  • 每个元素节点都使用 Hashtable,因此如果您重复它们,它们将被忽略。
  • 使用 DictionaryEntry 来允许同一个键有多个值。

关注点

实现自己的 AppSettings 读取器并不像您想象的那么难。当然,这取决于您想做多少,但读取 XmlNode 非常简单明了。您将收到一个包含 HashtableArrayListDictionaryEntriesArrayList。我知道这听起来可能很复杂,但搜索它们很容易,并且可以使用 foreach 来完成,就像在示例项目中展示的那样。

如果您 bother to look at the code,它看起来很简单,您不觉得吗?这对我有用,对您也可能有用,所以不妨看看。

总而言之,这可以帮助您为项目使用多个配置,只需通过更改 use 属性值即可打开或关闭它们,您还可以为同一个键插入多个值。

尽情享用!别忘了,任何评论、批评、问题或任何其他反馈都随时欢迎!

© . All rights reserved.