197 votes

Fichier de configuration de la DLL C#

J'essaie d'ajouter un fichier app.config à ma DLL, mais toutes mes tentatives ont échoué.

Selon MusicGenesis dans ' Mettre les informations de configuration dans une DLL Cela ne devrait pas poser de problème. Il est donc évident que je fais quelque chose de mal...

Le code suivant devrait renvoyer ma ConnectionString depuis ma DLL :

return ConfigurationManager.AppSettings["ConnectionString"];

Cependant, lorsque je copie le fichier app.config dans mon application console, tout fonctionne bien.

Des idées ?

0 votes

Selon l'article mentionné : si le nom de la dll est MyDll.dll, le fichier de configuration devrait être MyDLL.dll.config. Donc, si vous lisez les paramètres de configuration à l'intérieur de la dll, elle devrait faire référence à sa propre configuration, n'est-ce pas ?

11 votes

Peu importe le code demandé - il cherche le fichier tel que spécifié pour l'AppDomain : AppDomain.CurrentDomain.SetupInformation.ConfigurationFile setting

0 votes

Remarque : la question "mettre les informations de configuration dans une DLL" concerne la séparation du code de configuration de votre application dans une bibliothèque pour le garder séparé du code principal de l'application. C'est très différent d'un fichier de configuration séparé et spécial pour une DLL à part entière.

281voto

Chris Ammerman Points 6878

Il n'est pas facile de créer un fichier de configuration .NET pour une DLL, et ce pour une bonne raison. Le mécanisme de configuration de .NET intègre de nombreuses fonctionnalités pour faciliter la mise à niveau/mise à jour de l'application et pour empêcher les applications installées de piétiner les fichiers de configuration des autres.

Il y a une grande différence entre l'utilisation d'une DLL et l'utilisation d'une application. Il est peu probable que vous ayez plusieurs copies d'une application installées sur la même machine pour le même utilisateur. Mais vous pouvez très bien avoir 100 applications ou bibliothèques différentes qui utilisent toutes une DLL .NET.

Alors qu'il est rarement nécessaire de suivre les paramètres séparément pour les différentes copies d'une application au sein d'un même profil d'utilisateur, il est très Il est peu probable que vous souhaitiez que les différentes utilisations d'une DLL partagent la configuration les unes avec les autres. C'est pourquoi, lorsque vous récupérez un objet Configuration à l'aide de la méthode "normale", l'objet que vous obtenez est lié à la configuration du domaine d'application dans lequel vous vous exécutez, plutôt qu'à l'assemblage particulier.

Le domaine d'application est lié à l'assemblage Root qui a chargé l'assemblage dans lequel se trouve votre code. Dans la plupart des cas, il s'agit de l'assemblage de votre .EXE principal, qui a chargé la .DLL. Il est possible de créer d'autres domaines d'applications dans une application, mais vous devez fournir explicitement des informations sur l'assemblage racine de ce domaine d'applications.

En raison de tout cela, la procédure de création d'un fichier de configuration spécifique à une bibliothèque n'est pas si pratique. Il s'agit du même processus que celui que vous utiliseriez pour créer un fichier de configuration portable arbitraire qui ne serait pas lié à un assemblage particulier, mais pour lequel vous souhaitez utiliser le schéma XML de .NET, les mécanismes de section et d'élément de configuration, etc. Il s'agit de créer un fichier ExeConfigurationFileMap en chargeant les données pour identifier l'endroit où le fichier de configuration sera stocké, puis en appelant l'objet ConfigurationManager . OpenMappedExeConfiguration pour l'ouvrir dans un nouveau Configuration instance. Ce site sera vous couper de la protection de la version offerte par le mécanisme de génération automatique de chemins.

Statistiquement parlant, vous utilisez probablement cette bibliothèque dans un cadre interne, et il est peu probable que plusieurs applications l'utilisent sur une même machine/un même utilisateur. Mais Si ce n'est pas le cas, il y a quelque chose que vous devez garder à l'esprit. Si vous utilisez un seul fichier de configuration global pour votre DLL, quelle que soit l'application qui y fait référence, vous devez vous préoccuper des conflits d'accès. Si deux applications faisant référence à votre bibliothèque sont exécutées en même temps, chacune avec son propre fichier de configuration global, vous devez vous préoccuper des conflits d'accès. Configuration ouvert, alors lorsque l'un d'entre eux enregistre des modifications, cela provoquera une exception la prochaine fois que vous essaierez de récupérer ou d'enregistrer des données dans l'autre application.

Le moyen le plus sûr et le plus simple de contourner ce problème est d'exiger que l'assemblage qui charge votre DLL fournisse également des informations sur lui-même, ou de le détecter en examinant l'App Domain de l'assemblage qui le référence. Utilisez ceci pour créer une sorte de structure de dossier pour conserver des fichiers de configuration utilisateur séparés pour chaque application faisant référence à votre DLL.

Si vous êtes certains si vous souhaitez disposer de paramètres globaux pour votre DLL, quel que soit l'endroit où elle est référencée, vous devrez déterminer son emplacement plutôt que de laisser .NET trouver automatiquement l'emplacement approprié. Vous devrez également être agressif dans la gestion de l'accès au fichier. Vous devrez mettre en mémoire cache autant que possible, en gardant le fichier Configuration L'instance autour de SEULEMENT le temps qu'il faut pour charger ou sauvegarder, en ouvrant immédiatement avant et en jetant immédiatement après. Enfin, vous aurez besoin d'un mécanisme de verrouillage pour protéger le fichier pendant qu'il est modifié par l'une des applications qui utilisent la bibliothèque.

0 votes

Je pense que le mécanisme de synchronisation devrait être un "événement nommé", etc, parce qu'il est inter-processus.

9 votes

Meh. La nôtre est une application d'entreprise monstrueuse dont le fichier .exe principal a été écrit par des personnes situées dans un autre fuseau horaire et dont les modules sont représentés par diverses DLL et liés dynamiquement par un cadre de plugin personnalisé. Toute cette pomposité "vous devrez vous assurer que plusieurs applications peuvent utiliser votre DLL simultanément" est exactement fausse.

0 votes

En outre, pendant une grande partie de ma carrière, j'ai vu ces charmants mécanismes génériques d'objets partagés complètement ignorés, les équipes créant des DLL (ou des JAR) qui ne peuvent être utilisées que dans un seul contexte (et qui doivent être présentes, sinon l'application échoue). Ils pourraient tout aussi bien être liés statiquement, mais c'est dépassé.

105voto

Morbia Points 1004

Si vous voulez lire les paramètres du fichier de configuration de la DLL mais pas ceux des applications racine web.config ou app.config, utilisez le code ci-dessous pour lire la configuration dans la DLL.

var appConfig = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
string dllConfigData = appConfig.AppSettings.Settings["dllConfigData"].Value;

0 votes

En C++ géré pour VS 2008 System::Configuration::Configuration^ appConfig = ConfigurationManager::OpenExeConfiguration(Assembly::GetExecutingAssembly()->Location) ; String^ name = appConfig->AppSettings->Settings["name"]->Value ;

0 votes

Merci, cela a vraiment résolu mon problème. Je suis confronté à ce problème depuis environ deux jours et je n'ai réussi à le résoudre que maintenant. En déboguant un test, le ConfigurationManager lisait le fichier machine.config -je pense-, puisque les chaînes de connexion extraites concernaient SQLExpress -chaîne de connexion que je n'avais pas listée-.

22voto

Sven Points 184

J'ai eu le même problème et j'ai cherché sur le web pendant plusieurs heures mais je n'ai pas trouvé de solution alors j'ai fait la mienne. Je me suis demandé pourquoi le système de configuration de .net est si peu flexible.

Contexte : Je veux que mon DAL.dll ait son propre fichier de configuration pour la base de données et les paramètres DAL. J'ai également besoin du fichier app.config pour Enterprise Library et de ses propres configurations. J'ai donc besoin des deux fichiers app.config et dll.config.

Ce que je ne voulais pas faire, c'est transmettre chaque propriété/réglage de l'application à ma couche DAL !

pour détourner le "AppDomain.CurrentDomain.SetupInformation.ConfigurationFile" n'est pas possible car j'en ai besoin pour le comportement normal de l'app.config.

Mes exigences/points de vue étaient les suivants :

  • PAS de copie manuelle de quoi que ce soit de ClassLibrary1.dll.config à WindowsFormsApplication1.exe.config car cela n'est pas reproductible pour les autres développeurs.
  • conserver l'utilisation de la saisie forte "Properties.Settings.Default.NameOfValue" (comportement des paramètres) car je pense que c'est une fonctionnalité majeure et je ne voulais pas la perdre
  • J'ai constaté l'absence d'ApplicationSettingsBase pour injecter votre propre fichier de configuration ou de gestion (tous les champs nécessaires sont privés dans ces classes).
  • l'utilisation de la redirection du fichier "configSource" n'est pas possible parce que nous devrions copier/réécrire le fichier ClassLibrary1.dll.config et fournir plusieurs fichiers XML pour plusieurs sections (je n'ai pas non plus aimé cela)
  • Je n'ai pas voulu écrire mon propre SettingsProvider pour cette simple tâche, comme le suggère MSDN, car je pensais que ce serait tout simplement trop
  • Je n'ai besoin que des sections applicationSettings et connectionStrings du fichier de configuration.

J'ai modifié le fichier Settings.cs et implémenté une méthode qui ouvre le fichier ClassLibrary1.dll.config et lit les informations de la section dans un champ privé. Après cela, j'ai remplacé "this[string propertyName]" pour que le fichier Settings.Desginer.cs généré fasse appel à ma nouvelle propriété au lieu de la classe de base. Là, le paramètre est lu à partir de la liste.

Enfin, il y a le code suivant :

internal sealed partial class Settings
{
    private List<ConfigurationElement> list;

    /// <summary>
    /// Initializes a new instance of the <see cref="Settings"/> class.
    /// </summary>
    public Settings()
    {
        this.OpenAndStoreConfiguration();
    }

    /// <summary>
    /// Opens the dll.config file and reads its sections into a private List of ConfigurationElement.
    /// </summary>
    private void OpenAndStoreConfiguration()
    {
        string codebase = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
        Uri p = new Uri(codebase);
        string localPath = p.LocalPath;
        string executingFilename = System.IO.Path.GetFileNameWithoutExtension(localPath);
        string sectionGroupName = "applicationSettings";
        string sectionName = executingFilename + ".Properties.Settings";
        string configName = localPath + ".config";
        ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
        fileMap.ExeConfigFilename = configName;
        Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

        // read section of properties
        var sectionGroup = config.GetSectionGroup(sectionGroupName);
        var settingsSection = (ClientSettingsSection)sectionGroup.Sections[sectionName];
        list = settingsSection.Settings.OfType<ConfigurationElement>().ToList();

        // read section of Connectionstrings
        var sections = config.Sections.OfType<ConfigurationSection>();
        var connSection = (from section in sections
                           where section.GetType() == typeof(ConnectionStringsSection)
                           select section).FirstOrDefault() as ConnectionStringsSection;
        if (connSection != null)
        {
            list.AddRange(connSection.ConnectionStrings.Cast<ConfigurationElement>());
        }
    }

    /// <summary>
    /// Gets or sets the <see cref="System.Object"/> with the specified property name.
    /// </summary>
    /// <value></value>
    public override object this[string propertyName]
    {
        get
        {
            var result = (from item in list
                         where Convert.ToString(item.ElementInformation.Properties["name"].Value) == propertyName
                         select item).FirstOrDefault();
            if (result != null)
            {
                if (result.ElementInformation.Type == typeof(ConnectionStringSettings))
                {
                    return result.ElementInformation.Properties["connectionString"].Value;
                }
                else if (result.ElementInformation.Type == typeof(SettingElement))
                {
                    return result.ElementInformation.Properties["value"].Value;
                }
            }
            return null;
        }
        // ignore
        set
        {
            base[propertyName] = value;
        }
    }

Il vous suffira de copier votre ClassLibrary1.dll.config du répertoire de sortie de ClassLibrary1 vers le répertoire de sortie de votre application. Peut-être que quelqu'un trouvera cela utile.

14voto

Marc Gravell Points 482669

Lorsque l'on utilise ConfigurationManager, je suis presque sûr qu'il charge le process/ AppDomain fichier de configuration (app.config / web.config). Si vous voulez charger un fichier de configuration spécifique, vous devrez demander spécifiquement ce fichier par son nom...

Vous pouvez essayer :

var config = ConfigurationManager.OpenExeConfiguration("foo.dll");
config.ConnectionStrings. [etc]

0 votes

Selon l'article mentionné : si le nom de la dll est MyDll.dll, le fichier de configuration devrait être MyDLL.dll.config. Donc, si vous lisez les paramètres de configuration à l'intérieur de la dll, elle devrait faire référence à sa propre configuration, n'est-ce pas ?

1 votes

Non... je ne pense pas. "à partir de la dll" n'a pas de sens ; par défaut, il regarde le fichier de configuration défini pour l'AppDomain : my.exe.config

1 votes

En particulier, le paramètre AppDomain.CurrentDomain.SetupInformation.ConfigurationFile.

13voto

Jorge Córdoba Points 18919

ConfigurationManager.AppSettings renvoie les paramètres définis pour l'application, et non pour la DLL spécifique, vous pouvez y accéder mais ce sont les paramètres de l'application qui seront renvoyés.

Si vous utilisez la dll d'une autre application, la ConnectionString doit se trouver dans le fichier app.settings de l'application.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X