web-dev-qa-db-fra.com

Équivalent à 'app.config' pour une bibliothèque (DLL)

Existe-t-il un équivalent de app.config pour les bibliothèques (DLL)? Sinon, quel est le moyen le plus simple de stocker les paramètres de configuration spécifiques à une bibliothèque? Veuillez considérer que la bibliothèque peut être utilisée dans différentes applications.

140
Louis Rhys

Vous pouvez avoir un fichier de configuration séparé, mais vous devrez le lire "manuellement", le ConfigurationManager.AppSettings["key"] lira uniquement la configuration du en cours d'exécution Assemblée.

En supposant que vous utilisez Visual Studio en tant qu'EDI, vous pouvez cliquer avec le bouton droit sur le projet souhaité → Ajouter → Nouvel élément → Fichier de configuration de l'application.

Ceci ajoutera App.config dans le dossier du projet, mettez vos paramètres dans la section <appSettings>. Si vous n'utilisez pas Visual Studio et ajoutez le fichier manuellement, veillez à lui attribuer le nom suivant: DllName.dll.config , sinon le code ci-dessous ne fonctionnera pas correctement. .

Maintenant, lire à partir de ce fichier a une telle fonction:

string GetAppSetting(Configuration config, string key)
{
    KeyValueConfigurationElement element = config.AppSettings.Settings[key];
    if (element != null)
    {
        string value = element.Value;
        if (!string.IsNullOrEmpty(value))
            return value;
    }
    return string.Empty;
}

Et pour l'utiliser:

Configuration config = null;
string exeConfigPath = this.GetType().Assembly.Location;
try
{
    config = ConfigurationManager.OpenExeConfiguration(exeConfigPath);
}
catch (Exception ex)
{
    //handle errror here.. means DLL has no sattelite configuration file.
}

if (config != null)
{
    string myValue = GetAppSetting(config, "myKey");
    ...
}

Vous devrez également ajouter une référence à l'espace de noms System.Configuration afin de disposer de la classe ConfigurationManager.

Lors de la construction du projet, en plus du fichier DLL, vous aurez également le fichier DllName.dll.config, qui est le fichier que vous devez publier avec le fichier DLL lui-même.

Ce qui précède est un exemple de code de base. Pour ceux intéressés par un exemple à grande échelle, veuillez vous référer à cette autre réponse .

152
Shadow Wizard

Malheureusement, vous ne pouvez avoir qu’un seul fichier app.config par exécutable. Par conséquent, si des DLL sont liées à votre application, elles ne peuvent pas avoir leurs propres fichiers app.config.

La solution est: Il n'est pas nécessaire de placer le fichier App.config dans le projet de la bibliothèque de classes.
Vous insérez le fichier App.config dans l’application qui référence la DLL de votre bibliothèque de classes.

Par exemple, supposons que nous ayons une bibliothèque de classes nommée MyClasses.dll qui utilise le fichier app.config comme suit:

string connect = 
ConfigurationSettings.AppSettings["MyClasses.ConnectionString"];

Maintenant, supposons que nous ayons une application Windows nommée MyApp.exe qui référence MyClasses.dll. Il contiendrait un App.config avec une entrée telle que:

<appSettings>
    <add key="MyClasses.ConnectionString"
         value="Connection string body goes here" />
</appSettings>

OU

Un fichier xml est le meilleur équivalent pour app.config. Utilisez XML sérialiser/désérialiser au besoin. Vous pouvez appeler ça comme vous voulez. Si votre configuration est "statique" et n'a pas besoin de changer, vous pouvez également l'ajouter au projet en tant que ressource incorporée.

J'espère que ça donne une idée

28
PawanS

Les fichiers de configuration sont définis par l'application et non par l'assembly. Vous devrez donc placer les sections de configuration de votre bibliothèque dans le fichier de configuration de chaque application utilisant votre bibliothèque.

Cela dit, il est déconseillé d’obtenir la configuration à partir du fichier de configuration de l’application, en particulier de la section appSettings, dans une bibliothèque de classes. Si votre bibliothèque a besoin de paramètres, ceux-ci doivent probablement être passés comme arguments de méthode dans les constructeurs, les méthodes d'usine, etc. par celui qui appelle votre bibliothèque. Cela empêche les applications appelantes de réutiliser accidentellement les entrées de configuration attendues par la bibliothèque de classes.

Cela dit, les fichiers de configuration XML sont extrêmement pratiques. Le meilleur compromis que j'ai trouvé consiste à utiliser des sections de configuration personnalisées. Vous pouvez placer la configuration de votre bibliothèque dans un fichier XML automatiquement lu et analysé par le framework afin d'éviter tout risque d'accident.

Vous pouvez en apprendre plus sur les sections de configuration personnalisées sur MSDN et aussi Phil Haack a publié un article dans Nice dessus.

9
madd0
public class ConfigMan
{
    #region Members

    string _assemblyLocation;
    Configuration _configuration;

    #endregion Members

    #region Constructors

    /// <summary>
    /// Loads config file settings for libraries that use Assembly.dll.config files
    /// </summary>
    /// <param name="assemblyLocation">The full path or UNC location of the loaded file that contains the manifest.</param>
    public ConfigMan(string assemblyLocation)
    {
        _assemblyLocation = assemblyLocation;
    }

    #endregion Constructors

    #region Properties

    Configuration Configuration
    {
        get
        {
            if (_configuration == null)
            {
                try
                {
                    _configuration = ConfigurationManager.OpenExeConfiguration(_assemblyLocation);
                }
                catch (Exception exception)
                {
                }
            }
            return _configuration;
        }
    }

    #endregion Properties

    #region Methods

    public string GetAppSetting(string key)
    {
        string result = string.Empty;
        if (Configuration != null)
        {
            KeyValueConfigurationElement keyValueConfigurationElement = Configuration.AppSettings.Settings[key];
            if (keyValueConfigurationElement != null)
            {
                string value = keyValueConfigurationElement.Value;
                if (!string.IsNullOrEmpty(value)) result = value;
            }
        }
        return result;
    }

    #endregion Methods
}

Juste pour quelque chose à faire, j'ai reformulé la première réponse en classe. L'utilisation est quelque chose comme:

ConfigMan configMan = new ConfigMan(this.GetType().Assembly.Location);
var setting = configMan.GetAppSetting("AppSettingsKey");
5
Firegarden

Si vous ajoutez des paramètres à un projet de bibliothèque de classes dans Visual Studio (Propriétés du projet, Paramètres), un fichier app.config sera ajouté à votre projet avec les sections userSettings/applicatioNSettings appropriées et les valeurs par défaut de ces paramètres à partir de vos Settings.settings. fichier.

Toutefois, ce fichier de configuration ne sera pas utilisé au moment de l'exécution. À la place, la bibliothèque de classes utilise le fichier de configuration de son application d'hébergement.

Je pense que la principale raison de la génération de ce fichier est que vous pouvez copier/coller les paramètres dans le fichier de configuration de l'application hôte.

4
Joe

Je crée actuellement des plugins pour une marque de logiciel de vente au détail, qui sont en fait des bibliothèques de classes .net. Chaque plugin doit obligatoirement être configuré à l'aide d'un fichier de configuration. Après quelques recherches et tests, j'ai compilé le cours suivant. Il fait le travail sans faille. Notez que je n'ai pas implémenté la gestion des exceptions locales dans mon cas, car je intercepte les exceptions à un niveau supérieur.

Quelques ajustements peuvent être nécessaires pour obtenir le point décimal correct, en cas de nombres décimaux et de doublons, mais cela fonctionne bien pour CultureInfo ...

static class Settings
{
    static UriBuilder uri = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase);
    static Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(uri.Path);
    static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings");
    static NumberFormatInfo nfi = new NumberFormatInfo() 
    { 
        NumberGroupSeparator = "", 
        CurrencyDecimalSeparator = "." 
    };

    public static T Setting<T>(string name)
    {
        return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
    }
}

Exemple de fichier App.Config

<add key="Enabled" value="true" />
<add key="ExportPath" value="c:\" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />

Usage:

  somebooleanvar = Settings.Setting<bool>("Enabled");
  somestringlvar = Settings.Setting<string>("ExportPath");
  someintvar =     Settings.Setting<int>("Seconds");
  somedoublevar =  Settings.Setting<double>("Ratio");

Crédits à Shadow Wizard & MattC

3
Yiannis Leoussis

En réponse à la question initiale, j'ajoute généralement le fichier de configuration dans mon projet de test sous forme de lien. vous pouvez ensuite utiliser l'attribut DeploymentItem pour l'ajouter au dossier Out du test.

[TestClass]
[DeploymentItem("MyProject.Cache.dll.config")]
public class CacheTest
{
    .
    .
    .
    .
}

En réponse aux commentaires, les assemblages ne peuvent pas être spécifiques à un projet, ils le peuvent et cela offre une grande flexibilité, notamment. lorsque vous travaillez avec IOC framework.

2
Allan Elder

J'ai rencontré le même problème et l'ai résolu en créant une classe statique Parameters après avoir ajouté un fichier de configuration d'application au projet:

public static class Parameters
{
    // For a Web Application
    public static string PathConfig { get; private set; } =
        Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "web.config");

    // For a Class Library
    public static string PathConfig { get; private set; } =
        Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "LibraryName.dll.config");

    public static string GetParameter(string paramName)
    {
        string paramValue = string.Empty;

        using (Stream stream = File.OpenRead(PathConfig))
        {
            XDocument xdoc = XDocument.Load(stream);

            XElement element = xdoc.Element("configuration").Element("appSettings").Elements().First(a => a.Attribute("key").Value == paramName);
            paramValue = element.Attribute("value").Value;
        }

        return paramValue;
    }
}

Ensuite, obtenez un paramètre comme celui-ci:

Parameters.GetParameter("keyName");
2
krlzlx

les assemblys n'ont pas leur propre fichier app.config. Ils utilisent le fichier app.config de l'application qui les utilise. Donc, si votre Assemblée attend certaines choses dans le fichier de configuration, assurez-vous simplement que le fichier de configuration de votre application contient ces entrées.

Si votre assembly est utilisé par plusieurs applications, chacune de ces applications doit avoir ces entrées dans son fichier app.config.

Ce que je vous recommande de faire est de définir des propriétés sur les classes de votre assembly pour ces valeurs par exemple

private string ExternalServicesUrl
{
  get
  {
    string externalServiceUrl = ConfigurationManager.AppSettings["ExternalServicesUrl"];
    if (String.IsNullOrEmpty(externalServiceUrl))
      throw new MissingConfigFileAppSettings("The Config file is missing the appSettings entry for: ExternalServicesUrl");
    return externalServiceUrl;
  }
}

Ici, la propriété ExternalServicesUrl tire sa valeur du fichier de configuration de l'application. Si une application utilisant cet assemblage manque ce paramètre dans le fichier de configuration, vous aurez une exception: il est clair qu'il manque quelque chose.

MissingConfigFileAppSettings est une exception personnalisée. Vous voudrez peut-être lancer une exception différente.

Bien sûr, une meilleure conception serait que la méthode de ces classes reçoive ces valeurs en tant que paramètres plutôt que de s'appuyer sur le réglage du fichier de configuration. De cette manière, les applications utilisant ces classes peuvent décider d'où et comment elles fournissent ces valeurs.

1
Shiv Kumar

Utilisez ajouter un élément existant, sélectionnez la configuration d'application à partir du projet dll. Avant de cliquer sur ajouter, utilisez la petite flèche vers le bas à droite du bouton Ajouter pour "ajouter en tant que lien".

Je le fais tout le temps dans mon dev.

1
ghostJago

Préambule : J'utilise NET 2.0;

La solution publiée par Yiannis Leoussis est acceptable mais elle a posé quelques problèmes.

Tout d'abord, la static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings"); renvoie null. Je devais le changer en static AppSettingSection = myDllConfig.AppSettings;

Alors la return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi); n'a pas d'attrape pour les exceptions. Donc je l'ai changé

try
{
    return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
}
catch (Exception ex)
{
    return default(T);
}

Cela fonctionne très bien, mais si vous avez une DLL différente, vous devez réécrire à chaque fois le code de chaque Assemblée. Donc, voici ma version pour qu'une classe instancie chaque fois que vous en avez besoin.

public class Settings
{
    private AppSettingsSection _appSettings;
    private NumberFormatInfo _nfi;

    public Settings(Assembly currentAssembly)
    {
        UriBuilder uri = new UriBuilder(currentAssembly.CodeBase);
        string configPath = Uri.UnescapeDataString(uri.Path);
        Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(configPath);
        _appSettings = myDllConfig.AppSettings;
        _nfi = new NumberFormatInfo() 
        { 
            NumberGroupSeparator = "", 
            CurrencyDecimalSeparator = "." 
        };
    }


    public T Setting<T>(string name)
    {
        try
        {
            return (T)Convert.ChangeType(_appSettings.Settings[name].Value, typeof(T), _nfi);
        }
        catch (Exception ex)
        {
            return default(T);
        }
    }
}

Pour une config:

<add key="Enabled" value="true" />
<add key="ExportPath" value="c:\" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />

Utilisez-le comme:

Settings _setting = new Settings(Assembly.GetExecutingAssembly());

somebooleanvar = _settings.Setting<bool>("Enabled");
somestringlvar = _settings.Setting<string>("ExportPath");
someintvar =     _settings.Setting<int>("Seconds");
somedoublevar =  _settings.Setting<double>("Ratio");
1
Matteo Gaggiano

utiliser depuis des configurations doit être très très simple comme ceci:

var config = new MiniConfig("setting.conf");

config.AddOrUpdate("port", "1580");

if (config.TryGet("port", out int port)) // if config exist
{
    Console.Write(port);
}

pour plus de détails, voir MiniConfig

0
Rahmat Anjirabi

Pourquoi ne pas utiliser:

  • [ProjectNamespace].Properties.Settings.Default.[KeyProperty] pour C #
  • My.Settings.[KeyProperty] pour VB.NET

Il vous suffit de mettre à jour visuellement ces propriétés au moment de la conception:

[Solution Project]->Properties->Settings

0
Pedro Mora

Autant que je sache, vous devez copier + coller les sections de la bibliothèque .config que vous voulez dans le fichier .config des applications. Vous obtenez seulement 1 app.config par instance exécutable.

0
mike