Paramètres.Défaut. & Lt; propriété > renvoie toujours la valeur par défaut au lieu de la valeur dans le stockage persistant (fichier XML)

StackOverflow https://stackoverflow.com/questions/192641

Question

J'ai récemment écrit une DLL en C # (.Net 2.0) qui contient une classe nécessitant une adresse IP. Un de mes collègues a modifié la classe pour récupérer l'adresse IP d'un fichier ".dll.config". Fichier (XML) - Apparemment, il est généré automatiquement par les "Paramètres de l'application". le fichier qu'il a créé (Settings1.settings). L’avantage de cela était de permettre à l’utilisateur final de modifier l’adresse IP dans le fichier XML / config à sa guise.

Malheureusement, lorsque je récupère son code dans l'arborescence et que je tente de compiler (ou d'utiliser) ce nouveau code, toute application appelant cette DLL obtient uniquement la valeur par défaut, et non la valeur du fichier.

Le constructeur qui appelle le fichier de configuration se présente comme suit:

    public class form : System.Windows.Forms.Form
    {
        public form()
        {
            // This call is required by the Windows Form Designer.
            InitializeComponent();
            IP = IPAddress.Parse(Settings1.Default.IPAddress);
        }
    }

J'ai trouvé a référence à ce problème sur les forums MSDN où un utilisateur a déclaré:

  

les anciennes valeurs (celles que vous définissez au moment du développement) sont codées en dur. Si franework n'est pas en mesure d'accéder ou d'ouvrir le fichier de configuration, il utilisera les valeurs par défaut. Cela se produira toujours si vous utilisez des paramètres dans une dll.

  1. Est-ce que cela signifie que je ne peux pas stocker de valeur externe pour une DLL dans un fichier de configuration? (Mon collègue a en quelque sorte fait ce travail ...)

  2. Étant donné que mon framework ne semble pas pouvoir accéder au fichier de configuration ni y ouvrir, comment puis-je comprendre pourquoi il échoue? Ou même détecter quand cela se produit?

Decker : Cela aide un peu. Malheureusement, j'écris cette DLL dans une spécification, je n'ai donc pas accès au fichier de configuration de l'application. Comme vous le remarquerez plus haut, mon collègue a créé un "Paramètres 1 .settings". fichier. Je ne comprenais pas cela à ce moment-là, mais il semble maintenant que l’ajout du "1" le garde en dehors de l'espace de paramètres de toute application qui l'appelle.

Je suppose que ce que je cherche à comprendre, c'est pourquoi la DLL ne semble pas trouver le fichier de configuration à côté du fichier de configuration dans le même répertoire. Suivre le code pas à pas ne révèle rien.

En passant, je peux modifier le & type; Type de sortie " de mon assemblée à partir de " Class Library " vers " Application Windows " et ajoutez les lignes suivantes au début de mon code DLL:

    [STAThread]
    public static void Main(string[] args)
    {
        System.Windows.Forms.Application.Run(new form());
    }

Lorsque je lance ceci, il génère un fichier de configuration différent (un ".exe.config") et je peux le modifier et le faire extraire les nouvelles données du fichier. Donc je suis un peu confus. Des idées?

Était-ce utile?

La solution

J'aborde exactement ce problème dans une application où je suis en train de faire du prototypage. Bien que la suggestion de Decker de pirater les fichiers de configuration ensemble devrait fonctionner, je pense que c'est un piratage manuel assez peu pratique à effectuer dans le cadre d'un cycle de construction. Au lieu de cela, j'ai décidé que la solution la plus propre consiste à faire analyser chaque bibliothèque par son propre fichier library.dll.config. Ce n’est toujours pas parfait et il nécessite du code supplémentaire sur la plaque chauffante, mais cela semble être le seul moyen de contourner la méthode byzantine utilisée par .Net pour gérer ces fichiers app.config.

Autres conseils

J'utilise cette technique tout le temps. Souvent, j'ai un assemblage de bibliothèque qui nécessite certains paramètres, et j'ai besoin de les définir à la fois en testant des projets ainsi que le principal "exécutable". les assemblages, qu’ils soient des projets Web ou des projets de service Windows.

Vous avez raison de dire que lorsque vous créez un fichier de paramètres pour un projet, un fichier de configuration d'application est ajouté. La valeur que vous entrez pour n'importe quel paramètre est stockée à deux emplacements: le fichier de configuration ET dans les attributs des classes créées par l'infrastructure de paramètres. Lorsqu'un fichier de configuration n'est pas trouvé, les valeurs incorporées dans les attributs sont utilisées.

Voici un extrait qui montre un tel attribut:

Voici un extrait qui indique la valeur par défaut de ConcordanceServicesEndpointName dans la classe générée:

    [global::System.Configuration.ApplicationScopedSettingAttribute()]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Configuration.DefaultSettingValueAttribute("InternalTCP")]

    public string ConcordanceServicesEndpointName {
        get {
            return ((string)(this["ConcordanceServicesEndpointName"]));
        }
    }

Ce que vous voulez faire est de copier la section de configuration du fichier app.config du projet d'assemblage de la bibliothèque et de la fusionner (soigneusement) dans le fichier web.config ou app.config approprié pour l'assembly principal. Au moment de l'exécution, c'est le seul fichier de configuration utilisé.

Voici un exemple:

<configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
      <section name="LitigationPortal.Documents.BLL.DocumentsBLLSettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
  </configSections>
  <applicationSettings>
    <LitigationPortal.Documents.BLL.DocumentsBLLSettings>
      <setting name="ConcordanceServicesEndpointName" serializeAs="String">
        <value>InternalTCP</value>
      </setting>
    </KayeScholer.LitigationPortal.Documents.BLL.DocumentsBLLSettings>
  </applicationSettings>

Vous devez copier ces sections dans le "vrai". fichier de configuration.

J'ai le même problème depuis longtemps - c'est agaçant.

J'aime l'idée de créer votre propre fichier de configuration et de le faire analyser par chaque DLL, même s'il peut toujours être facile de ne pas avoir à changer de configuration.

Une chose que j’ai faite par le passé pour au moins un peu plus de facilité est de s’assurer que les valeurs de configuration pour lesquelles le fichier Setting1.Settings est invalide.

Par exemple, j'ai une classe qui utilise LINQ-To-SQL pour communiquer avec la base de données. Il contient donc un fichier Setting1.settings dans lequel il stocke la chaîne de connexion dans la base de données. La valeur par défaut entrée (lors du glisser-déposer des tables de la base de données dans le concepteur) est la chaîne de connexion de la base de données dev.

Une fois que le fichier DBML a été créé à partir de la base de test, je peux modifier le fichier de paramètres, puis taper un nom de base de données du type "FAKE_DATABASE".

Ainsi, si vous utilisez la DLL dans un autre projet et oubliez de fusionner les fichiers de configuration pour ajouter la valeur de configuration appropriée à la DLL, vous obtiendrez au moins le message d'erreur "Impossible de se connecter à FAKE_DATABASE ".

Bien sûr, si vous devez travailler à nouveau avec le concepteur, vous devrez redéfinir la valeur sur celle de votre base de données dev.

douleur énorme. Ils doivent changer cela d'une façon ou d'une autre.

Apparemment, votre application tente de lire le fichier de configuration par défaut (qui est probablement le fichier de configuration de l'application). Pour être sûr, ajoutez la paire clé-valeur dans le fichier de configuration de la DLL au fichier de configuration de l'application, exécutez l'application et voyez si elle est lue cette fois-ci.

Je pense avoir trouvé une explication de la raison pour laquelle cela ne fonctionne pas pour ma DLL et mon application de test. Voici l'exception finale du blog de certains gars :

  

La solution à cela est de s’assurer que votre application et les assemblys de support ont le même espace de nom ou de fusionner le contenu de AppName.exe.config et DllName.dll.config (oui lorsque vous compilez un fichier .dll). maintenant, il génère ce fichier, mais il est ignoré si vous le copiez dans le répertoire de l'application et qu'il n'est pas automatiquement fusionné.

Donc, je dois soit conserver la DLL et l'application dans le même espace de noms -ou- je dois fusionner le contenu du fichier de configuration de la DLL avec le fichier de configuration de l'application.

(Cela ne va-t-il pas à l'encontre de l'objectif de la DLL? Je pensais qu'une DLL était censée être une bibliothèque indépendante.)

C’est peut-être pour cette raison que cela fonctionne pour mon collègue. L'application de production partage le même espace de noms que la DLL. (Mon application de test ne clairement pas ...)

MISE À JOUR: Je viens tout juste de m'asseoir récemment avec mon collègue pour reparler de ce problème. Il semble que cela n'a jamais fonctionné pour lui non plus, mais il ne s'en était pas rendu compte car définir la valeur initiale pour être le même que le périphérique que nous essayions d'utiliser. Bien sûr, cela a semblé fonctionner au début, mais dès que nous l'avons déployé ailleurs avec des réglages légèrement différents, il a de nouveau été cassé.

J'ai rencontré un problème similaire lors de l'utilisation de app.config. Essayez d’exécuter votre application à partir du fichier .exe au lieu de Visual Studio & amp; voyez si elle se comporte comme prévu.

Il est possible que dans votre DLL, le modificateur d'accès (pour Settings1.Settings) soit défini sur Internal (Friend for VB). Essayez de changer le Access MOdifier sur Public et voyez si cela permet à votre application de lire / écrire les valeurs de la configuration de la DLL.

La réponse de Howard couvre la théorie.

Un moyen rapide et approprié de résoudre ce problème consiste à analyser manuellement le fichier de configuration xml.

    string configFile = Assembly.GetExecutingAssembly().Location + ".config";
    XDocument.Load(configFile).Root.Element("appSettings")....

L'erreur que je pense que vous faites tous est que vous faites apparemment référence aux paramètres de la DLL via Settings1.Default.IPAddress alors que vous êtes simplement autorisé à le faire Settings1.IPAddress .

La différence est que lorsque vous utilisez Settings1.Default.IPAddress , les valeurs sont obtenues à partir des valeurs codées en dur insérées dans le fichier d'assembly (.dll ou .exe) en tant qu'attribut [global :: System. Configuration.DefaultSettingValueAttribute (...)].

While Settings1.IPAddress est la valeur modifiable dans le fichier .dll.config (fichier XML) **. Par conséquent, toutes les modifications que vous apportez au fichier XML ne sont pas reflétées dans la valeur par défaut codée en dur dans l'assemblage.

Pas cela:

IP = IPAddress.Parse(Settings1.Default.IPAddress);

Mais essayez ceci:

*IP = IPAddress.Parse(Settings1.IPAddress);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top