c# speichern Settings.Default.<Eigenschaft> gibt immer den Standardwert anstelle des Werts im persistenten Speicher zurück(XML-Datei)



c# settings read write (8)

Ich habe vor kurzem eine DLL in C # (.Net 2.0) geschrieben, die eine Klasse enthält, die eine IP-Adresse benötigt. Ein Kollege von mir änderte die Klasse, um die IP aus einer ".dll.config" (XML) -Datei abzurufen - Diese wird scheinbar automatisch von der Datei "Application Settings" erzeugt, die er erstellt hat (Settings1.settings). Der Vorteil war, dass der Endbenutzer die IP-Adresse in der XML- / Konfigurationsdatei beliebig ändern konnte.

Leider, wenn ich seinen Code aus der Baumstruktur überprüfe und versuche, diesen neuen Code zu kompilieren (oder zu verwenden), erhält jede Anwendung, die diese DLL aufruft, nur den Standardwert und nicht den Wert aus der Datei.

Der Konstruktor, der die Konfigurationsdatei aufruft, sieht folgendermaßen aus:

    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);
        }
    }

Ich habe einen Verweis auf dieses Problem in den MSDN-Foren gefunden, in denen ein Benutzer sagte:

Die "alten" Werte (die Sie zur Entwicklungszeit definieren) sind fest codiert. Wenn das franework nicht in der Lage ist, auf die Konfigurationsdatei zuzugreifen oder sie zu öffnen, verwendet sie stattdessen die Standardeinstellungen. Dies wird immer passieren, wenn Sie Einstellungen in einer DLL verwenden.

  1. Bedeutet das, dass ich keinen externen Wert für eine DLL in einer Konfigurationsdatei speichern kann? (Mein Kollege hat diese Arbeit irgendwie gemacht ...)

  2. Da mein Framework anscheinend nicht in der Lage ist, auf die Konfigurationsdatei zuzugreifen oder sie zu öffnen, wie finde ich heraus, warum sie fehlschlägt? Oder sogar erkennen, wenn das passiert?

Decker : Das hilft ein bisschen. Leider schreibe ich diese DLL zu einer Spezifikation, also habe ich nicht wirklich Zugriff auf die Konfigurationsdatei der Anwendung. Wie Sie oben bemerkt haben, hat mein Kollege eine "Settings 1 .settings" -Datei erstellt. Ich habe das zu der Zeit nicht verstanden, aber jetzt scheint es, dass das Hinzufügen der "1" es aus dem Einstellungsraum jeder Anwendung heraushält, die es aufruft.

Ich denke, ich versuche herauszufinden, warum die DLL nicht scheint, die Konfigurationsdatei zu finden, die neben ihr im selben Verzeichnis sitzt. Schritt für Schritt zeigt der Code nichts.

Nebenbei kann ich den "Ausgabetyp" meiner Assembly von "Class Library" zu "Windows Application" ändern und die folgenden Zeilen am Anfang meines DLL-Codes hinzufügen:

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

Wenn ich das ausführe, erzeugt es eine andere Konfigurationsdatei (eine ".exe.config") und diese kann ich ändern und die neuen Daten aus der Datei ziehen lassen. Also bin ich ein bisschen verwirrt. Irgendwelche Ideen?


Answer #1

Ich hatte dieses Problem schon lange - es ist nervig.

Ich mag die Idee, Ihre eigene Konfigurationsdatei zu erstellen und jede DLL zu analysieren, obwohl es immer noch leicht sein könnte, die Konfiguration zu ändern.

Eine Sache, die ich in der Vergangenheit getan habe, um es ein wenig einfacher zu machen, ist sicherzustellen, dass alle Konfigurationswerte der Setting1.Settings-Datei ungültig sind.

Zum Beispiel habe ich eine Klasse, die LINQ-To-SQL verwendet, um mit der DB zu sprechen. Es enthält also eine Setting1.settings-Datei, in der die Verbindungszeichenfolge für die Datenbank gespeichert wird. Der Standardwert, der beim Drag & Drop der Datenbanktabellen in den Designer eingegeben wird, ist die Verbindungszeichenfolge der Dev-Datenbank.

Sobald ich die DBML-Datei basierend auf der Testdatenbank erstellt habe, kann ich die Einstellungsdatei öffnen und bearbeiten und einen Datenbanknamen wie "FAKE_DATABASE" eingeben.

Wenn Sie die DLL in einem anderen Projekt verwenden und dann vergessen, die Konfigurationsdateien zusammenzuführen, um den richtigen Konfigurationswert für die DLL hinzuzufügen, erhalten Sie zumindest eine Fehlermeldung wie "Verbindung zu FAKE_DATABASE nicht möglich".

Wenn Sie erneut mit dem Designer arbeiten müssen, müssen Sie den Wert natürlich wieder auf den Wert Ihrer Entwicklungsdatenbank zurücksetzen.

Großer Schmerz. Sie müssen das irgendwie ändern.


Answer #2

Ich denke, ich habe gerade eine Erklärung gefunden, warum das nicht für meine DLL und meine Testanwendung funktioniert. Hier ist die abschließende Ausnahme vom Blog eines Kerls :

Das Problem besteht darin, entweder sicherzustellen, dass Ihre Anwendung und die Support-Assemblies über denselben Namespace verfügen oder dass Sie den Inhalt von AppName.exe.config und DllName.dll.config zusammenführen (Ja, wenn Sie eine DLL kompilieren, die jetzt generiert wird Diese Datei wird jedoch ignoriert, wenn Sie sie in das Anwendungsverzeichnis kopieren und nicht automatisch zusammengeführt werden.)

Entweder muss ich die DLL und die Anwendung im selben Namespace behalten - oder - ich muss den Inhalt der DLL-Konfigurationsdatei mit der Konfigurationsdatei der Anwendung zusammenführen.

(Beseitigt dies nicht den Zweck der DLL? Ich dachte, eine DLL sollte eine unabhängige Bibliothek sein.)

Vielleicht ist das der Grund, warum es für meinen Kollegen funktioniert. Die Produktionsanwendung nutzt denselben Namespace wie die DLL. (Meine Test App funktioniert eindeutig nicht ...)

UPDATE: Ich habe mich erst kürzlich mit meinem Kollegen zusammengesetzt und habe wieder über dieses Problem gesprochen und es scheint, dass es auch nie für ihn funktioniert hat, aber er hatte es nicht bemerkt, weil er den Anfangswert so eingestellt hatte wie der Gerät, das wir verwenden wollten. Natürlich schien es zuerst zu funktionieren, aber sobald wir es anderswo mit etwas anderen Einstellungen eingesetzt hatten, war es wieder kaputt.


Answer #3

Es ist möglich, dass Sie in Ihrer DLL den Zugriffsmodifikator (für die Settings1.Settings) auf Internal (Friend for VB) festgelegt haben. Versuchen Sie, den Access MOdifier auf "Public" zu ändern und zu überprüfen, ob Ihre Anwendung dadurch Werte aus der DLL-Konfiguration lesen / schreiben kann.


Answer #4

Ich benutze diese Technik die ganze Zeit. Oft habe ich eine Bibliothek Assembly, die bestimmte Einstellungen erfordert, und ich brauche sie sowohl durch das Testen von Projekten als auch die primäre "ausführbare" Assemblys - sei es Web-Projekte oder Windows-Dienst-Projekte.

Sie haben Recht, wenn Sie eine Einstellungsdatei für ein Projekt erstellen, fügt sie eine Anwendungskonfigurationsdatei hinzu. Der Wert, den Sie für eine Einstellung eingeben, wird an zwei Stellen gespeichert - der Konfigurationsdatei UND in Attributen für die Klassen, die von der Einstellungsinfrastruktur erstellt wurden. Wenn keine Konfigurationsdatei gefunden wird, werden die in die Attribute eingebetteten Werte verwendet.

Hier ist ein Ausschnitt, der ein solches Attribut zeigt:

Hier ist ein Auszug, der den Standardwert des ConcordanceServicesEndpointName in der generierten Klasse zeigt:

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

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

Sie möchten den Konfigurationsabschnitt aus der Bibliothek "app.config" aus dem Bibliotheksmontageprojekt kopieren und ihn (vorsichtig) in die entsprechende Datei web.config oder app.config für die Hauptbaugruppe einfügen. Zur Laufzeit ist dies die einzige Konfigurationsdatei, die verwendet wird.

Hier ist ein Beispiel:

<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>

Sie sollten diese Abschnitte in die Konfigurationsdatei "true" kopieren.


Answer #5

Anscheinend versucht Ihre Anwendung, von der Standardkonfigurationsdatei (die wahrscheinlich die Konfigurationsdatei der Anwendung ist) zu lesen. Um sicherzustellen, fügen Sie das Schlüssel-Wert-Paar in der Konfigurationsdatei der DLL der Konfigurationsdatei der Anwendung hinzu, führen Sie die Anwendung aus und sehen Sie, ob sie diesmal gelesen wird.


Answer #6

Die Antwort von Howard deckt die Theorie ab.

Ein schneller und schmutziger Weg, dies zu lösen, besteht darin, die XML-Konfigurationsdatei manuell zu analysieren.

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

Answer #7

Ich habe ein ähnliches Problem bei der Verwendung von app.config festgestellt. Versuchen Sie, Ihre Anwendung von der EXE-Datei aus anstatt von Visual Studio auszuführen, und sehen Sie, ob sie sich dann wie erwartet verhält.


Answer #8

Der Fehler, den ich denke, dass Sie alle machen, ist, dass Sie anscheinend auf die DLL-Einstellungen über Settings1.Default.IPAddress verweisen, während Sie einfach dazu aufgefordert werden, diese Settings1.IPAddress durchzuführen.

Der Unterschied besteht darin, dass bei der Verwendung von Settings1.Default.IPAddress die Werte aus den hartcodierten Werten abgerufen werden, die in der Assemblydatei (.dll oder .exe) als Attribut [global :: System.Configuration.DefaultSettingValueAttribute (...)] enthalten sind.

Während Settings1.IPAddress der Wert ist, der in der Datei .dll.config (XML-Datei) ** bearbeitet werden kann. Wenn Sie also Änderungen an der XML-Datei vornehmen, wird dies nicht in den fest codierten Standardwerten in der Baugruppe widergespiegelt.

Nicht das:

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

Aber versuche das:

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




application-settings