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

发布于 2024-08-01 21:54:28 字数 1772 浏览 11 评论 0原文

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

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 中。 在哪里可以找到我的弦乐收藏?

I am accessing my assembly's configuration like this:

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

My .config file contains a section like this

<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>

I can successfully read the connection strings including changes if I edit the .config file. So, I know I am connected to the correct file. But I cannot find that string collection inside of the appSettings object. It is is not in the .Settings KeyValueConfigurationCollection. Where do I find my string collection?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦魇绽荼蘼 2024-08-08 21:54:28

连接字符串通常位于配置管理器的 ConnectionStrings 属性内。 您应该能够通过其静态方法以更简单的方式进行访问。

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

我相信您应该在 .config 文件中使用标签“AppSettings”而不是“ApplicationSettings”,以使 ConfigurationManager 能够通过 AppSettings 属性进行访问。

我不太了解 ConfigurationManager 的工作原理,无法确保这会解决您的问题,但重命名它并删除该自定义部分组应该允许 AppSettings 正常工作。

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

You connection strings are typically inside of the configuration manager's ConnectionStrings property. You should be able to access in a much simpler fashion through its static method.

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

I believe you should use the tag "AppSettings" instead of "ApplicationSettings" in the .config file to enable the ConfigurationManager to access through the AppSettings property.

I don't know enough about how ConfigurationManager works to be sure this will solve your problem, but renaming it and removing that custom section group should allow AppSettings to work properly.

Edit
Yes, it appears that ConfigurationManager's AppSettings property accesses the section named
in the .config file.

可是我不能没有你 2024-08-08 21:54:28

您应该使用这个更简单的语法访问集合中的项目

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);
}

可能有更短的方法,但这对我有用。

You should be access the items in the collection using this simpler syntax

foreach (string s in CsDll.Properties.Settings.Default.StpInsertSearchPath)
{
    Console.WriteLine(s);
}

EDIT:

The following code should do the trick

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);
}

There may be a shorter way, but this works for me.

深海夜未眠 2024-08-08 21:54:28

如果它是一个 StringCollection,您尝试从设置中提取

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

将完成同样多的任务,而不需要 XmlSerializer

if it is a StringCollection you are trying to extract from the settings

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

will accomplish as much with out the need for XmlSerializer

梦归所梦 2024-08-08 21:54:28

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

然而,applicationSettingsuserSettings(它们对应于您可以在VS设置设计器中编辑的熟悉的Settings.settings)并不那么容易获得在。 AppSettingsapplicationSettings 不同,后者位于所使用的配置文件的完全不同的部分。

您必须使用上述挖掘方法或其变体来获取 applicationSettingsuserSettings。 此外,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"));
    }

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

练习者)

 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 一起使用,可能还添加了一些保存方法等等,并且您确实需要跟踪(或多或少)多个配置文件中的哪些实际上正在运行 - 主文件、漫游文件或本地文件。

我为什么要这样做? 因为两个相关的应用程序和一个公共类库(或多个库)都需要使用其中一个应用程序所拥有的相同设置,其中设置是可视化管理的。 有没有人以更好的方式解决这个问题?

谢谢。

AppSettings and ConnectionStrings are both properties directly available on the ConfigurationManager.

However, applicationSettings and userSettings, which correspond to the familiar Settings.settings you can edit in the VS settings designer, are not so easy to get at. AppSettings is NOT the same as applicationSettings which is in an entirely different section of the config file in use.

You must use the mining approach above or a variant to get at applicationSettings and userSettings. Also, the applicationSettings will only update next time you start the application, if you are even able to write to them at all at runtime.

For example (cribbed from elsewhere - thank you):

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;
    }

and for another example (adaoted from many examples - thank you to the world):

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

Then, unfortunately you still have to deal with the SettingElement objects that are in the settings collection in these sections. Each one has to deserialized to the property Type unless it is a string e.g. for an applicationSettings SettingElement (one that cannot be dynamically updated at runtime):

(exerciser)

 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);
        }

For a string property it is easier (this example is essentially redundant with the first one above):

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

All of these examples fiddled with applicationSettings. The same approach can work with userSettings with the addition of probably some save methods and so on, and you do need to keep track (more or less) of which of the several many config files are actually in play - main, roaming, or local.

Why am I doing this? Because two related applications and a common class library (or libraries) all need to use the same settings owned by one of the applications where the settings are visually managed. Has anyone solved this in a better way?

Thanks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文