通过配置管理器从AppSettings获取StringCollection

5
我正在这样访问我的程序集配置:

ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = Assembly.GetExecutingAssembly().Location + ".config";
Configuration conf = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
AppSettingsSection appSettings = conf.AppSettings;

我的.config文件包含以下部分:
<configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
        <section name="CsDll.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
</configSections>
<connectionStrings>
    <add name="CsDll.Properties.Settings.SabreCAD" connectionString="A Connection string." />
    <add name="CsDll.Properties.Settings.StpParts" connectionString="Another connection string" />
</connectionStrings>
 <applicationSettings>
        <CsDll.Properties.Settings>
            <setting name="StpInsertSearchPath" serializeAs="Xml">
                <value>
                    <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                        <string>A string</string>
                        <string>Another string in the collection</string>

我可以成功读取连接字符串,如果我编辑.config文件,包括更改。因此,我知道我已经连接到正确的文件。但是我无法在appSettings对象中找到该字符串集合。它不在.Settings KeyValueConfigurationCollection中。我在哪里找到我的字符串集合?

4个回答

6
您应该使用这种更简单的语法来访问集合中的项目。
foreach (string s in CsDll.Properties.Settings.Default.StpInsertSearchPath)
{
    Console.WriteLine(s);
}

编辑:

下面的代码应该可以解决问题

ExeConfigurationFileMap map = new ExeConfigurationFileMap(); 
map.ExeConfigFilename = Assembly.GetExecutingAssembly().Location + ".config"; 
Configuration conf = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None); 
ConfigurationSectionGroup appSettingsGroup = conf.GetSectionGroup("applicationSettings");
ClientSettingsSection clientSettings = (ClientSettingsSection) appSettingsGroup.Sections["CsDll.Properties.Settings"];
ConfigurationElement element = clientSettings.Settings.Get("StpInsertSearchPath");
string xml = ((SettingElement)element).Value.ValueXml.InnerXml;
XmlSerializer xs = new XmlSerializer(typeof(string[]));
string[] strings = (string[])xs.Deserialize(new XmlTextReader(xml, XmlNodeType.Element, null));
foreach (string s in strings)
{
    Console.WriteLine(s);
}

也许有更短的方法,但这个对我有效。

好的。我可以这样读取字符串数组。但是,这些字符串来自默认编译到程序集中。我需要能够在程序集部署后添加、删除和更改该集合中的字符串。.Properties.Settings.Default不会捕获对.config文件的编辑。 直到我开始通过ConfigurationManager进行操作,才解决了连接字符串的相同问题。 - Rodney Schuler
你可能需要访问ConfigurationManager的方法:ConfigurationManager.GetSection("applicationSettings");它应该返回你想要分析的对象。 - jkelley
ConfigurationManager.GetSection("applicationSettings") 返回 null。 - Rodney Schuler
2
请参考我的编辑。它通过巧妙的方式找到配置文件中适当的XML元素,然后使用标准的Xml序列化调用进行反序列化。 - Michael A. McCloskey
请参考@Kevin Stout的下面的答案。这是一个更简单、更易于实现的解决方案。请注意,他的答案比原始答案晚了2.5年,但至少对于VS2013来说,看起来是一个更好的答案。 - STLDev

3

如果你需要从设置中提取StringCollection

var strings = (StringCollection) Properties.Settings.Default["StpInsertSearchPath"];

将不需要XmlSerializer就能完成相同的工作

2

AppSettings和ConnectionStrings都是直接在ConfigurationManager上可用的属性。

然而,与您可以在VS设置设计器中编辑的熟悉的Settings.settings相对应的applicationSettings和userSettings并不容易获得。AppSettings与完全不同的配置文件部分中的applicationSettings不同。

您必须使用上面提到的挖掘方法或其变体才能获取applicationSettings和userSettings。此外,如果您在运行时能够写入它们,applicationSettings只会在下次启动应用程序时更新。

例如(从其他地方抄袭 - 谢谢):

public static string ReadSetting(string sectionGroupName, string sectionName, string settingName, Configuration config = null)
    {
        if (config == null)
            config = SharedConfigSettings;
        // Get sectionGroup
        var sectionGroup =
          config.GetSectionGroup(sectionGroupName);

        // Get section
        var section =
          (ClientSettingsSection)sectionGroup.Sections.Get(sectionName);
        // Get setting
        var setting = section.Settings.Get(settingName);
        // Read setting value
        return setting.Value.ValueXml.InnerText;
    }

另一个例子(改编自许多例子 - 感谢全世界):

///<summary>
    /// return the applicationSettings section 
    ///</summary>
    ///<returns></returns>
    public static ClientSettingsSection GetSettingsSection(ConfigurationSectionGroup group, string clientSectionName)
    {
        return (ClientSettingsSection)group.Sections[clientSectionName];
    }


    ///<summary>
    /// return the section settings collection
    ///</summary>
    ///<returns></returns>
    public static System.Configuration.SettingElementCollection GetSettingsCollection(ClientSettingsSection section)
    {
        return section.Settings;
    }

    ///<summary>
    /// return the connectionStrings section collection
    ///</summary>
    ///<returns></returns>
    public static System.Configuration.SettingElementCollection ConnectionStringsCollection()
    {
        return ((ClientSettingsSection)SharedConfigSettings.GetSection("connectionStrings")).Settings;
    }

    ///<summary>
    /// A collection of all the UserSettings in a SettingElementCollection
    ///</summary>
    ///<returns></returns>
    public static SettingElementCollection UserSettings()
    {
        return
            GetSettingsCollection(GetSettingsSection(GetSettingsSectionGroup(@"userSettings"),
                                                     @"MyAssembly.Properties.Settings"));
    }

    ///<summary>
    /// A collection of all the ApplicationSettings in a SettingElementCollection
    ///</summary>
    ///<returns></returns>
    public static SettingElementCollection ApplicationSettings()
    {
        return
            GetSettingsCollection(GetSettingsSection(GetSettingsSectionGroup(@"applicationSettings"),
                                                     @"MyAssembly.Properties.Settings"));
    }

不幸的是,您仍然需要处理这些部分中设置集合中的SettingElement对象。除非是一个字符串(例如applicationSettings SettingElement,无法在运行时动态更新),否则每个对象都必须反序列化为属性类型:

(练习者)

 var y = GetSettingsSection(GetSettingsSectionGroup(@"applicationSettings"), @"MyAssembly.Properties.Settings");
 var c = (y.Settings.Cast<SettingElement>().FirstOrDefault(s => s.Name == "WellKnownDirectories").Value).ValueXml
                .InnerXml; // the setting as Xml
 var xs = new XmlSerializer(typeof(string[]));
 var strings = (string[])xs.Deserialize(new XmlTextReader(c, XmlNodeType.Element, null));

foreach (string s in strings)
        {
            Console.WriteLine(s);
        }

对于字符串属性,更容易实现(这个例子与上面的第一个例子基本重复):

var s = (y.Settings.Cast<SettingElement>().FirstOrDefault(s => s.Name == "MyUserSettingName").Value).ValueXml
                .InnerText

所有这些示例都涉及到了applicationSettings。同样的方法也可以用于userSettings,只需要添加一些保存方法等,并且您确实需要(或多或少地)跟踪哪些配置文件实际上在运行-主要是漫游或本地文件。
我为什么要这样做呢?因为两个相关的应用程序和一个公共类库(或者几个库)都需要使用由其中一个应用程序拥有的设置,而这些设置可以在该应用程序中进行可视化管理。有人找到更好的解决方法吗?
谢谢。

1

你的连接字符串通常在配置管理器的ConnectionStrings属性中。你应该能够通过它的静态方法更简单地访问。

string myConnectionString = ConfigurationManager.ConnectionStrings["connectioStringName"];

我认为你应该在.config文件中使用标签“AppSettings”而不是“ApplicationSettings”,以便ConfigurationManager可以通过AppSettings属性进行访问。

我对ConfigurationManager的工作原理了解不够,无法确定这是否能解决你的问题,但重命名并删除自定义部分组应该可以使AppSettings正常工作。

编辑 是的,看起来ConfigurationManager的AppSettings属性访问了.config文件中命名的部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接