web-dev-qa-db-fra.com

Lire le fichier de configuration personnalisé en C # (Framework 4.0)

Je développe une application en C # sous Framework 4.0.

Dans mon application, je souhaite créer un fichier de configuration séparé qui n'est pas le fichier app.config. Le fichier de configuration contient des sections de configuration personnalisées que nous avons développées pour le produit.

Je ne veux pas faire référence à ce fichier depuis app.config à l'aide de configSource. 

Je veux le charger au moment de l'exécution et lire son contenu.

Un exemple de ce que je veux dire est le log4net qui vous permet d'écrire la configuration dans le fichier log4net.config.

Quelqu'un peut-il aider à faire cela sans écrire de code qui imite le code qui existe dans le framework?

METTRE À JOUR:

basé sur la réponse de Kaido J'ai écrit une classe utilitaire qui lit le fichier de configuration personnalisé et a la possibilité d'actualiser le contenu de la configuration lorsque le fichier sur le système de fichiers est modifié.

L'utilisation dans cette classe est la suivante:

  1. Obtenir le contenu du fichier de configuration

    // Create configuration reader that reads the files once
    var configFileReader = new CustomConfigurationFileReader("c:\\myconfig.config");
    var config = configFileReader.Config;
    
    // Do any action you want with the config object like:
    config.GetSection("my.custom.section");
    
    // or,
    var someVal = config.AppSettings.Settings["someKey"];
    
  2. Recevoir des notifications lorsque le fichier de configuration change

    // Create configuration reader that notifies when the configuraiton file changes
    var configFileReader = new CustomConfigurationFileReader("c:\\myconfig.config", true);
    
    // Register to the FileChanged event
    configFileReader.FileChanged += MyEventHandler;
    
    ...
    
    private void MyEventHanler(object sender, EventArgs e)
    {
         // You can safely access the Config property here, it is already contains the new content
    }
    

Dans le code, j'ai utilisé PostSharp pour valider le paramètre d'entrée du constructeur afin de vérifier que le fichier journal n'est pas nul et que le fichier existe. Vous pouvez modifier le code pour que ces validations soient intégrées au code (bien que je recommande d’utiliser PostSharp pour séparer l’application en aspects).

Voici le code:

    using System;
    using System.Configuration;
    using System.IO;
    using CSG.Core.Validation;

    namespace CSG.Core.Configuration
    {
        /// <summary>
        /// Reads customer configuration file
        /// </summary>
        public class CustomConfigurationFileReader
        {
            // By default, don't notify on file change
            private const bool DEFAULT_NOTIFY_BEHAVIOUR = false;

            #region Fields

            // The configuration file name
            private readonly string _configFileName;

            /// <summary>
            /// Raises when the configuraiton file is modified
            /// </summary>
            public event System.EventHandler FileChanged;

            #endregion Fields

            #region Constructor

            /// <summary>
            /// Initialize a new instance of the CustomConfigurationFileReader class that notifies 
            /// when the configuration file changes.
            /// </summary>
            /// <param name="configFileName">The full path to the custom configuration file</param>
            public CustomConfigurationFileReader(string configFileName)
                : this(configFileName, DEFAULT_NOTIFY_BEHAVIOUR)
            {            
            }        

            /// <summary>
            /// Initialize a new instance of the CustomConfigurationFileReader class
            /// </summary>
            /// <param name="configFileName">The full path to the custom configuration file</param>
            /// <param name="notifyOnFileChange">Indicate if to raise the FileChange event when the configuraiton file changes</param>
            [ValidateParameters]
            public CustomConfigurationFileReader([NotNull, FileExists]string configFileName, bool notifyOnFileChange)
            {
                // Set the configuration file name
                _configFileName = configFileName;

                // Read the configuration File
                ReadConfiguration();

                // Start watch the configuration file (if notifyOnFileChanged is true)
                if(notifyOnFileChange)
                    WatchConfigFile();
            }

            #endregion Constructor        

            /// <summary>
            /// Get the configuration that represents the content of the configuration file
            /// </summary>
            public System.Configuration.Configuration Config
            {
                get;
                set;
            }

            #region Helper Methods

            /// <summary>
            /// Watch the configuraiton file for changes
            /// </summary>
            private void WatchConfigFile()
            {
                var watcher = new FileSystemWatcher(_configFileName);
                watcher.Changed += ConfigFileChangedEvent;
            }

            /// <summary>
            /// Read the configuration file
            /// </summary>
            public void ReadConfiguration()
            {
                // Create config file map to point to the configuration file
                var configFileMap = new ExeConfigurationFileMap
                {
                    ExeConfigFilename = _configFileName
                };

                // Create configuration object that contains the content of the custom configuration file
                Config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
            }        

            /// <summary>
            /// Called when the configuration file changed.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void ConfigFileChangedEvent(object sender, FileSystemEventArgs e)
            {
                // Check if the file changed event has listeners
                if (FileChanged != null)
                    // Raise the event
                    FileChanged(this, new EventArgs());
            }

            #endregion Helper Methods
        }
    }
37
Koby Mizrahy
 // Map the roaming configuration file. This
      // enables the application to access 
      // the configuration file using the
      // System.Configuration.Configuration class
      ExeConfigurationFileMap configFileMap =
        new ExeConfigurationFileMap();
      configFileMap.ExeConfigFilename = 
        roamingConfig.FilePath;

      // Get the mapped configuration file.
      Configuration config =
        ConfigurationManager.OpenMappedExeConfiguration(
          configFileMap, ConfigurationUserLevel.None);

de http://msdn.Microsoft.com/en-us/library/system.configuration.configurationmanager.aspx

18
Kaido

Dans le passé, j’utilisais Nini - http://nini.sourceforge.net/manual.php qui vous permet de lire/écrire des fichiers de configuration personnalisés (XML/Ini/Registry/.Config) à l’exécution.

J'espère que cela t'aides.

6
christofr

Mon conseil avec la configuration est de créer votre propre composant pour le lire.
Cela peut faciliter le développement si, à un moment donné, vous décidiez d’obtenir la configuration à partir d’une autre source, telle qu’une base de données ou un service Web.
Ce type d’abstraction vous aide également à vous moquer de la configuration et augmente la testabilité (quelque chose que le framework .NET ne fait pas du tout bien).
Si vous utilisez XML comme format de configuration, je suggère d’utiliser Linq to XML.
Il est plus facile à lire et à utiliser pour analyser des fichiers XML.

2
the_drow

Vous pouvez essayer cadre Cinchoo pour vos besoins. Cela simplifie le travail de développement en abordant d'abord le code. Définir une classe comme ci-dessous,

namespace HelloWorld
{
    #region NameSpaces

    using System;
    using Cinchoo.Core.Configuration;

    #endregion NameSpaces

    [ChoConfigurationSection("sample")]
    public class SampleConfigSection : ChoConfigurableObject
    {
        #region Instance Data Members (Public)

        [ChoPropertyInfo("name", DefaultValue="Mark")]
        public string Name;

        [ChoPropertyInfo("message", DefaultValue="Hello World!")]
        public string Message;

        #endregion
    }

    static void Main(string[] args)
    {
        SampleConfigSection sampleConfigSection = new SampleConfigSection();
        Console.WriteLine(sampleConfigSection.ToString());
    }

}

Pour la première fois, lorsque vous exécuterez l’application, la section de configuration sera créée dans le fichier .xml [appexename] comme ci-dessous. Ensuite, toute modification apportée à ce fichier sera automatiquement prise en compte. 

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="sample" type="Cinchoo.Core.Configuration.ChoNameValueSectionHandler, Cinchoo.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de" />
  </configSections>
  <sample>
    <add key="name" value="Mark" />
    <add key="message" value="Hello World!" />
  </sample>
</configuration>
2
nittuj

Ou utilisez NameValueCollection easy 

0
Damian