📜 ⬆️ ⬇️

App.Config and Custom Configuration Sections

This article may seem trivial, but sometimes something useful is forgotten, and laziness is not read in an imported language and books are not at hand. Therefore, I turned to Google and found a good description of the process of creating a processor of the configuration section of the app.config file in .net applications, translated it, added remarks (italics) and comments, and decided to publish it.

I am sure that many of you have had to use the App.Config configuration file to store the initialization or configuration data of the application. And I am also sure that many of you wanted to create your own structures in this file for storing settings. But in the end, you had to use the built-in capabilities of the <appSettings> section and get the values ​​using the following construction:

ConfigurationManager.AppSettings["MyKey"] 

')
Well, I have long wanted to figure out how to use the capabilities of the ConfigurationSection class to describe and load data defined in my own format. After several hours of experiments and googling, I was able to create my own data structure in the configuration file and use it in my application.

So, in order to load our data structure from the App.Config file, we need the following classes:
  1. ConfigurationSection - This object will return us the user section.
  2. ConfigurationElementCollection - This is the actual collection of items that we define in the user section.
  3. ConfigurationElement - This is the element itself that describes an entity you define.



The first thing we need to do is add the app.Config file to our application (unless, of course, you haven’t already done this). Then open this file and copy-paste the following code between the <configuration> tags:

 <configSections> <!-- name = ,          . type =   .   :   -      +   ,  ,    . --> <section name="StartupFolders" type="ConfigSectionTester.StartupFoldersConfigSection, ConfigSectionTester"/> </configSections> 


Note: this section should be located at the very beginning of the configuration file, i.e. immediately after the <configuration> tag, otherwise there will be configuration initialization errors.

Next, create our own section that will implement our own data model:

 <StartupFolders> <Folders> <add folderType="A" path="c:\foo" /> <add folderType="B" path="C:\foo1" /> </Folders> </StartupFolders> 


Note: if someone doesn’t like adding nodes with the add command in this example, you can always make your own prefix using the following code:
 [ConfigurationCollection( typeof( FolderElement ) ), AddItemName = "Folder"] public class FoldersCollection : ConfigurationElementCollection { 

when defining a collection of elements in a data structure. Then in the configuration file you can write as follows:
 <StartupFolders> <Folders> <Folder folderType="A" path="c:\foo" /> <Folder folderType="B" path="C:\foo1" /> </Folders> </StartupFolders> 



We finish the modifications in the configuration file and move on to organizing the interaction of our application with it.

First of all, we will create a class derived from ConfigurationSection, which will allow us to interact with our section in the configuration file via the ConfigurationManager during program execution.

 public class StartupFoldersConfigSection : ConfigurationSection { [ConfigurationProperty( "Folders" )] public FoldersCollection FolderItems { get { return ( (FoldersCollection)( base[ "Folders" ] ) ); } } } 

The ConfigurationProperty attribute (“Folders”) is required to map the FolderItems property to the root node of our data structure.

The FoldersCollection class is a successor of the ConfigurationElementCollection, which provides interaction with the collection of our elements described in app.config. The class is defined as:

 [ConfigurationCollection( typeof( FolderElement ) )] public class FoldersCollection : ConfigurationElementCollection { protected override ConfigurationElement CreateNewElement() { return new FolderElement(); } protected override object GetElementKey( ConfigurationElement element ) { return ( (FolderElement)( element ) ).FolderType; } public FolderElement this[int idx ] { get{return (FolderElement) BaseGet(idx); } } } 


Last we need to create a ConfigurationElement, a class that will link us to the final data defined in the configuration file.

 public class FolderElement : ConfigurationElement { [ConfigurationProperty("folderType", DefaultValue="", IsKey=true, IsRequired=true)] public string FolderType { get {return ((string) (base["folderType"]));} set{base["folderType"] = value; } } [ConfigurationProperty( "path", DefaultValue = "", IsKey = false, IsRequired = false )] public string Path { get{return ( (string)( base[ "path" ] ) ); } set{base[ "path" ] = value; } } } 


The ConfigurationProperty attribute (“folderType”) is required in order to associate the name of the xml attribute in the configuration file. Other attribute parameters such as DefaultValue = "", IsKey = true, IsRequired = true define only the various options applicable to the properties.

Note: the author is silent on the fact that with the standard method of using the setter of the FolderType property, it will not work, because The configuration file is usually read only. In order to make it possible to write to the configuration file, you should do this, for example:

 Configuration cfg = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); StartupFoldersConfigSection section = (StartupFoldersConfigSection)cfg.Section["StartupFolders"]; if ( section != null ) { System.Diagnostics.Debug.WriteLine( section.FolderItems[0].FolderType ); System.Diagnostics.Debug.WriteLine( section.FolderItems[0].Path ); section.FolderItems[0].Path = "C:\\Nanook"; cfg.Save(); //        <exename>.vshost.exe.config     . } 


So, we have all the necessary data and classes that provide us with the ability to store a custom data structure in the app.config configuration file.
You can use this approach as follows:

 StartupFoldersConfigSection section = (StartupFoldersConfigSection)ConfigurationManager.GetSection( "StartupFolders" ); if ( section != null ) { System.Diagnostics.Debug.WriteLine( section.FolderItems[ 0 ].FolderType ); System.Diagnostics.Debug.WriteLine( section.FolderItems[ 0 ].Path ); } 

In this case, do not forget to register the System.Configuration in the list of pluggable namespaces.

Posted by: Derik Whittaker

Source: https://habr.com/ru/post/128517/


All Articles