NameValueSectionHandler - can i use this section type for writing back to the application config file?

后端 未结 2 397
攒了一身酷
攒了一身酷 2021-01-27 04:56

back to the topic of why didn\'t .net provide a simple (i don\'t want to implement \"ConfigurationSection\" \"ConfigurationElement\" \"ConfigurationProperty\" for 2 val

相关标签:
2条回答
  • 2021-01-27 04:59

    You need to load the config file in the right way. Rather than using the static properties of ConfigurationManager use the methods to load.

    Also you need to ensure you are managing the difference between global, application, user roaming and user local configuration. Normally only the last two should be writeable.

    Some test code for writing changes to the use config file:

    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
    TestConfigData data = (TestConfigData)config.GetSection("testConfigData");
    ++data.Data;
    config.Save(ConfigurationSaveMode.Minimal);
    

    Where TestConfigDate is a custom configuration type:

    using System;
    using System.Configuration;
    using System.Text;
    
    namespace CustomConfiguration {
      public class TestConfigData : ConfigurationSection {
    
        [ConfigurationProperty("Name", IsRequired=true)]
        public string Name {
          get {
            return (string)this["Name"];
          }
          set {
            this["Name"] = value;
          }
        }
    
        [ConfigurationProperty("Data", IsRequired=false),
         IntegerValidator(MinValue=0)]
        public int Data {
          get {
            return (int)this["Data"];
          }
          set {
            this["Data"] = value;
          }
        }
      }
    }
    

    And the configuration file contains, noting the allowExeDefinition attribute on the section element to define that a user configuration file and override the app.exe.config:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
        <section name="testConfigData"
                 type="CustomConfiguration.TestConfigData, CustomConfiguration"
                 allowExeDefinition="MachineToLocalUser"/>
      </configSections>
    
      <testConfigData Name="Fubar" Data="0"/>
    </configuration>
    
    0 讨论(0)
  • 2021-01-27 05:09
    • No - NameValueSectionHandler does not assist the user in 'creating' the Xml that will be written to the app.config file.

    Fire up reflector and take a look at the following method on System.Configuration.NameValueSectionHandler : internal static object CreateStatic(object parent, XmlNode section, string keyAttriuteName, string valueAttributeName).

    Linda Liu from Microsoft Online Community Support gives some great information about NameValueSectionHandler, IConfigurationSectionHandler, and why a DefaultSection instance will be returned from Configuration.GetSection(string) in a discussion at the EggHeadCafe forums: Backwards compatibility of System.Configuration.Configuration.

    It is technically possible to read, and create this information, but I recommend you not cause yourself more pain than you must by interacting at this extremely low level of the Configuration API. Please use the below code for Educational purposes only. I highly encourage you to use one of the methods like what Richard mentioned using the declarative style for creating a custom ConfigurationSection

    app.config

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <configSections>
            <section name="SingleTag" type="System.Configuration.SingleTagSectionHandler"/>
        </configSections>
        <SingleTag scheme="https" server="webmail.contoso.com" domain="CONTOSO" username="jdoe" password="iTz@s3Cr3t!"/>
    </configuration>`
    

    You could read this configuration section, but it's not good for your mental health.

    Sample C# Code - Stick this inside your void Main(string[] args) and smoke it.

    // Read configuration
    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
    ConfigurationSection readableSection = config.GetSection("SingleTag");
    string readableSectionRawXml = readableSection.SectionInformation.GetRawXml();
    XmlDocument readableSectionRawXmlDocument = new XmlDocument();
    readableSectionRawXmlDocument.Load(new StringReader(readableSectionRawXml));
    SingleTagSectionHandler readableSectionHandler = new SingleTagSectionHandler();
    Hashtable result = (Hashtable)readableSectionHandler.Create(null, null, readableSectionRawXmlDocument.DocumentElement);
    foreach (string item in result.Keys)
    {
        Console.WriteLine("{0}\t=\t{1}", item, result[item]);
    }
    
    // Create similar configuration section
    Hashtable mySettings = new Hashtable();
    mySettings.Add("key1", "value1:" + DateTime.Now);
    mySettings.Add("key2", "value2:" + DateTime.Now);
    mySettings.Add("key3", "value3:" + DateTime.Now);
    mySettings.Add("keynull", null);
    mySettings.Add("key4", "value4:" + DateTime.Now);
    string rawData = string.Empty;
    XmlDocument writableSectionXmlDocument = new XmlDocument();
    XmlElement rootElement = writableSectionXmlDocument.CreateElement("CreateSingleTag");
    foreach (var item in mySettings.Keys)
    {
        if (mySettings[item] != null)
        {
            rootElement.SetAttribute(item.ToString(), mySettings[item].ToString());
        }
    }
    writableSectionXmlDocument.AppendChild(rootElement);
    
    if (config.Sections.Get("CreateSingleTag") == null)
    {
        ConfigurationSection writableSection = new DefaultSection();
        writableSection.SectionInformation.SetRawXml(writableSectionXmlDocument.OuterXml);
        config.Sections.Add("CreateSingleTag", writableSection);
    }
    else
    {
    config.Sections["CreateSingleTag"].SectionInformation.SetRawXml(writableSectionXmlDocument.OuterXml);
    }
    
    config.Save();
    

    For completeness sake - you need the following usings

    using System;
    using System.Collections;
    using System.Configuration;
    using System.IO;
    using System.Xml;
    

    and a reference to at least the following assemblies

    System
    System.Configuration
    System.Xml
    
    0 讨论(0)
提交回复
热议问题