Les fichiers de configuration en C#

Dans cet article, nous allons parler des fichiers de configuration en C#.

Ces fichiers ont l’avantage d’être lisible par un être humain et modifiable grâce à n’importe quel éditeur de texte.

1-A quoi servent-ils

Les fichiers de configurations, (nommés app.config  par défaut, web.config pour les programmeurs ASP), permettent d’être beaucoup plus souple lors de l’écriture d’un programme. Ces fichiers sont composés de données (par exemple sous la forme de paires clef-valeur) qui pourront être utilisées lors de l’exécution du programme.

Dans la pratique ces données sont chargés une fois en cache au démarrage. Cependant il est toujours possible d’interagir avec les fichiers à tout moment du RunTime (voir dernière partie).

2-Comment les utiliser

Tout d’abord vous devez ajouter un fichier de configuration à votre projet principal de votre solution.

Clic droit sur le projet puis add new item puis choisir Application Configuration File.

Vous devriez voir à la racine de votre projet un fichier app.config.

Ensuite votre projet doit référencer System.Configuration (où se trouve la classe ConfigurationManager).

°Le fichier de configuration minimum (contenu du app.config):

<!--Entete classique d'un fichier xml -->
<?xml version="1.0" encoding="utf-8"?>
<!--Une partie configuration, la partie qui sera 'scannée' par la
classe statique System.Configuration.ConfigurationManager-->
<configuration>
        <!--Une section appSettings, section prédéfinie par défaut fournie
par le  Framework .NET-->
        <appSettings>
                <!--Les entrées sont de la forme clef-valeur-->
                <add key="clef" value="valeur"/>
        </appSettings>
</configuration>

°Au niveau du code : Au niveau du code vous pouvez accéder à ces données comme suit :

var mesConfigurations = ConfigurationManager.AppSettings;
string maClef = "clef";
string maValeur = mesConfigurations[maClef];
//Renvoit "valeur" selon le fichier de configuration minimal décrit plus tôt.

le type de mesConfiguration est NameValueCollection, qui hérite de NameObjectCollectionBase, lui même implémente en particulier les interfaces ICollection et IEnumerable. Ceci pour dire que son contenu est facilement manipulable, l’auto completion vous aidera à trouver la primitive qui vous intéresse (AllKeys, GetValues(string key), …).

3-Les sections

il est possible d’appeler à partir de votre fichier de configuration principal d’autres fichiers de configuration, afin de séparer ce qui doit être séparé, les chaines de connexion dans un fichier séparé, les préférences utilisateur dans un autre fichier …

Sur notre exemple au-dessus, nous avions le minimum, une seule section « appSettings », dans ce cas, autant laisser cette section telle quelle dans le app.config. Mais imaginons qu’on ait beaucoup plus de section, notre fichier de configuration deviendrai vite illisible.

Il est possible d’externaliser toute section dans un autre fichier qui sera référencé dans le fichier de configuration principal.

L’utilisation de fichiers externes apporte une structure plus cohérente et modulaire aux fichiers de configuration.

Cela permet de gérer restreindre l’accès aux sections de paramètres de configuration sensibles.

Les paramètres d’un fichier externes peuvent être modifiés et rechargés sans nécessiter un redémarrage de l’application.

Pour les intégrer il y a deux cas différents :

°grace à l’attribut file :

Fonctionnalité limitée à la section appSettings uniquement, permet de fusionner les clefs déclarés avec celles d’un autre fichier de configuration.

EXEMPLE:

app.config :

<?xml version="1.0" encoding="utf-8"?>
<configuration>
        <!--Les entrées sont de la forme clef-valeur-->
        <appSettings file="./mesSettingsFusionnes.config">
                <add key="clef3" value="valeur3"/>
        </appSettings>
</configuration>

mesSettingsFusionnes.config :

<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
        <add key="clef1" value="valeur1" />
        <add key="clef2" value="valeur2" />
</appSettings>

Je cite msdn qui se passe de tout commentaires :

« Dans la mesure où toute modification du fichier Web.config provoque le redémarrage de l’application, l’utilisation d’un fichier distinct permet aux utilisateurs de modifier des valeurs figurant dans la section appSettings sans entraîner le redémarrage de l’application. Le contenu du fichier distinct est fusionné avec la section appSettings du fichier Web.config. Cette fonctionnalité est limitée à l’attribut appSettings. »

 

°grace à l’attribut configSource :

La première solution est à éviter pour pas mal de raisons, la plus évidente me semble qu’avoir une source de donnée divisé dans deux fichiers différents peut apporter des confusions.

L’autre solution possible est l’attribut configSource, c’est identique sauf qu’il faut déplacer la section entière dans le fichier distinct car les paramètres des éléments ne sont pas fusionnés. De plus cette attribut est utilisable par tout les éléments de configuration.

Pour l’exemple , il existe une autre section prédéfinie dans la partie configuration: la section <connectionStrings>, regardons comment l’utiliser :

app.config :

<?xml version="1.0" encoding="utf-8"?>
<configuration>
        <appSettings file="./mesSettingsFusionnes.config">
                <add key="clef3" value="valeur3"/>
        </appSettings>
        <connectionStrings configSource="mesConnections.config"/>
</configuration>

mesConnections.config :

<?xml version="1.0"?>
<connectionStrings>
  <add name="defaut" connectionString="Data Source='toDefine';UserID='toDefine';Password='toDefine'" providerName="System.Data.OracleClient" />
</connectionStrings>

Attention, pour une raison inconnue, il n’est pas possible de spécifier un fichier n’appartenant pas au dossier courant ou à un des sous-dossier du dossier courant, sous peine de recevoir l’exception suivante :

System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize ---&gt;
System.Configuration.ConfigurationErrorsException: The configSource attribute is invalid.: The configSource '..\test.config' is invalid. It must refer to a file in the same directory or in a subdirectory as the configuration file. (MonTest.dll.config line 7) 
System.ArgumentException: The configSource '..\test.config' is invalid. It must refer to a file in the same directory or in a subdirectory as the configuration file.

Une solution simple est de mettre un autre app.config dans un autre répertoire et l’ouvrir avec

System.Configuration.ConfigurationManager.OpenExeConfiguration("MyAltDirectory");

Il est possible de définir ses propres sections (voir dans les liens utiles).

4- Le pattern GetOrDefault

Dans la catégorie best practices, je voudrais dédier une partie sur un design pattern lié au pattern TryGet, nommons le  GetOrDefault, il permet de récupérer la valeur si elle est dans le fichier de configuration, ou une valeur par défaut sinon.

Il est intéressant d’utiliser une classe statique comprenant l’ensemble de ces méthodes à utiliser directement comme dans l’exemple suivant :

static class MesConfigurations
{
        public static bool GetBool(string myField, bool defaultValue){
            bool result;
                string value = ConfigurationManager.AppSettings[myField];
                if(valeur == null || !bool.TryParse(value, out result)){
                        return defaultValue;
                }
                return result;
        }
        //...
}

 4- Modifier le App config au runTime

Il faut tout d’abord garder à l’esprit que modifier et persister les valeurs au runTime ou recharger les valeurs à partir du fichier de configuration sont des opérations couteuses a éviter si possible.

Lorsque vous récupérez la section AppSettings grace à la propriété ConfigurationManager.AppSettings, elle est en lecture seule. Cependant il est possible de modifier ses données et de constater la modification de façon persistante dans le fichier de configuration. Pour faire une modification d’une à partir de sa clé, vous devez procéder comme suit :

Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
 
config.AppSettings.Settings.Remove(clef);
 
config.AppSettings.Settings.Add(clef,valeur);
 
config.Save(ConfigurationSaveMode.Modified);

Vous pouvez rafraichir une section à tout moment grâce a la ligne suivante:

ConfigurationManager.RefreshSection("appSettings");

Dans une optique d’élimination des magic string, l’utilisation de fichier de configuration est une solution flexible.

voir :

http://msdn.microsoft.com/fr-fr/library/ee523958.aspx

http://blog.the-dargans.co.uk/2007/01/try-get-design-pattern.html

http://nico-pyright.developpez.com/tutoriel/vc2005/configurationsectioncsharp/

Comments are closed.