【问题标题】:Custom configuration settings, custom ClientSettingsSection自定义配置设置,自定义ClientSettingsSection
【发布时间】:2018-10-05 05:28:59
【问题描述】:

考虑以下配置部分:

<configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <section name="xxx.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
    </sectionGroup>
</configSections>
<applicationSettings>
    <xxx.Properties.Settings>
        <setting name="xxx_Service1" serializeAs="String">
            <value>https://xxx.service1</value>
        </setting>
        <setting name="xxx_Service1" serializeAs="String">
            <value>https://xxx.service2</value>
        </setting>
        <setting name="xxx_Service1" serializeAs="String">
            <value>https://xxx.service3</value>
        </setting>
    </xxx.Properties.Settings>
</applicationSettings>

我尝试实现 System.Configuration.ClientSettingsSection 的自定义版本。我需要完全相同的层次结构

ConfigSection     
  -  ConfigElement      
  -  ConfigElement     
  -  ConfigElement

基于AssemblyExplorer的代码我编写了自定义实现:

{
    static void Main()
    {
        var sec = (CustomClientSettingsSection) ConfigurationManager.GetSection("serviceSettings");
        Console.Read();
    }
}

public class CustomClientSettingsSection : ConfigurationSection
{
    private static readonly ConfigurationProperty _propSettings = new ConfigurationProperty((string)null,
        typeof(CustomSettingElementCollection), (object)null, ConfigurationPropertyOptions.IsDefaultCollection);

    [ConfigurationProperty("", IsDefaultCollection = true)]
    public CustomSettingElementCollection Services
    {
        get { return (CustomSettingElementCollection)this[CustomClientSettingsSection._propSettings]; }
    }
}

public class CustomSettingElementCollection : ConfigurationElementCollection
{
    protected override ConfigurationElement CreateNewElement()
    {
        return new CustomSettingElement();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((CustomSettingElement)element).Key;
    }
}

public class CustomSettingElement : ConfigurationElement
{
    private static readonly ConfigurationProperty _propName = new ConfigurationProperty("name", typeof(string), (object)"", ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey);

    internal string Key
    {
        get
        {
            return this.Name;
        }
    }

    [ConfigurationProperty("name", DefaultValue = "", IsKey = true, IsRequired = true)]
    public string Name
    {
        get
        {
            return (string)this[CustomSettingElement._propName];
        }
        set
        {
            this[CustomSettingElement._propName] = (object)value;
        }
    }
}

我正在尝试解析这个 config.xml

  <configSections>
    <section name="serviceSettings" type="ConsoleApplication1.CustomClientSettingsSection, ConsoleApplication1"/>
  </configSections>
  <serviceSettings>
    <setting name="xxx_Service1">
    </setting>
    <setting name="xxx_Service2">
    </setting>
  </serviceSettings>

我得到错误:

无法识别的元素“设置”。

如何解析此配置并获取具有相同属性的configElement 列表?

【问题讨论】:

  • 我建议使用 XmlDocument 和 .GetElementsByTagName("setter")
  • 我在配置文件中使用自定义配置,我必须使用 ConfigurationManager 阅读
  • 我建议改用 .NET Core 引入的新配置类。这些包符合 .NET 标准,这意味着它们也可以被完整的框架项目使用。您不需要 任何 代码来定义部分并将设置解析为对象。

标签: c# .net


【解决方案1】:

这是我从这里改编的代码以适合您的示例。

Code Project: Custom Configuration Sections in app.config or web.config

我使用 Powershell 和 VS Code 测试 C# 代码

csc TestCodeApp.cs
.\TestCodeApp.exe

TestCodeApp.exe.config

<configuration>
    <configSections>
        <section name="Services" type="TestCodeApp.ServicesConfig, TestCodeApp"/>
    </configSections>
    <Services>
        <setting name="xxx_Service1" value="this1"/>
        <setting name="xxx_Service2" value="this2"/>
    </Services>
</configuration>

TestCodeApp.cs

using System;
using System.Configuration;
using System.Diagnostics;

namespace TestCodeApp {

    class TestCode {
        static void Main () {
            ExeConfigurationFileMap configMap = new ExeConfigurationFileMap { ExeConfigFilename = "TestCodeApp.exe.config" };
            Configuration config = ConfigurationManager.OpenMappedExeConfiguration (configMap, ConfigurationUserLevel.None);

            var section = (ServicesConfig) config.GetSection ("Services");

            // This fixes the below error
            // error CS0122: 'System.Configuration.ConfigurationElement.this[System.Configuration.ConfigurationProperty]' is inaccessible due to its protection level
            section.SectionInformation.UnprotectSection ();

            var services = section.Services;

            for (int i = 0; i < services.Count; i++)
            {
                Console.WriteLine(services[i].Name + " - " + services[i].Value);
            }            
        }
    }

    public class ServicesConfig : ConfigurationSection {
        [ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)]
        [ConfigurationCollection(typeof(ServicesCollection), AddItemName = "setting")]
        public ServicesCollection Services {
            get { return ((ServicesCollection) (this[""])); }
        }
    }

    [ConfigurationCollection (typeof (ServicesElement))]
    public class ServicesCollection : ConfigurationElementCollection {
        protected override ConfigurationElement CreateNewElement () {
            return new ServicesElement ();
        }

        protected override object GetElementKey (ConfigurationElement element) {
            return ((ServicesElement) (element)).Name;
        }

        public ServicesElement this [int index] {
            get {
                return (ServicesElement) BaseGet (index);
            }
        }
    }

    public class ServicesElement : ConfigurationElement {
        [ConfigurationProperty ("name", DefaultValue = "",
            IsKey = true, IsRequired = true)]
        public string Name {
            get {
                return ((string) (base["name"]));
            }
            set {
                base["name"] = value;
            }
        }

        [ConfigurationProperty ("value", DefaultValue = "",
            IsKey = false, IsRequired = false)]
        public string Value {
            get {
                return ((string) (base["value"]));
            }
            set {
                base["value"] = value;
            }
        }      
    }
}

我对其进行了测试,效果很好。如果您有任何问题,请告诉我。

【讨论】:

  • 感谢您的回答和时间。你举了一个标准的例子。它工作正常,但问题是不同的。在您的文件中: Section->ElementCollection ->Elements ,在我的文件中: Section->Elements. Section 和 Element 节点之间没有 CustomSettingElementCollection。在 之后去
  • 好的。我收回我的话。可以办到。我刚刚有一个灵光乍现的时刻。我编辑了答案。
  • 关键是使用 IsDefaultCollection=true 和 this[""] 能够访问该部分本身而不是另一个节点下的集合。
猜你喜欢
  • 2011-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-27
  • 2015-05-01
相关资源
最近更新 更多