app.config für eine Klassenbibliothek

80

Ich kann keine app.config-Datei sehen, die vom VS2008-Assistenten für eine Klassenbibliothek generiert wurde. Bei meinen Recherchen habe ich festgestellt, dass in einer Anwendung nur eine app.config vorhanden ist.

Ist es eine schlechte Sache, eine app.config manuell zu einer Klassenbibliothek hinzuzufügen, oder gibt es andere Methoden, die den Zweck einer app.config in der Klassenbibliothek erfüllen?

Ich muss log4net-Konfigurationsinformationen in der Datei app.config speichern.

logeeks
quelle
2
Sie können Ihre ausführbare Projektkonfigurationsdatei aus Ihrer Bibliothek lesen.
Akram Shahda

Antworten:

98

Sie sollten einem Klassenbibliotheksprojekt im Allgemeinen keineapp.config Datei hinzufügen . Es wird nicht ohne schmerzhaftes Biegen und Verdrehen von Ihrer Seite verwendet. Es schadet dem Bibliotheksprojekt überhaupt nicht - es macht einfach überhaupt nichts.

Stattdessen konfigurieren Sie die Anwendung, die Ihre Bibliothek verwendet. Die erforderlichen Konfigurationsinformationen würden also dorthin gehen. Jede Anwendung, die möglicherweise Ihre Bibliothek verwendet, hat wahrscheinlich andere Anforderungen, daher ist dies auch logisch sinnvoll.

Andrew Barber
quelle
23
Schön für dich. Ich habe Ihre Frage jedoch nicht beantwortet. Sie haben eindeutig ein eigenes Konfigurationssystem, das nicht für die Person gilt, die hier die Frage stellt.
Andrew Barber
1
Ich habe eine Selenium WebDriver-Klassenbibliothek, die ich für alle meine Testfälle von NUnit aus ausführe. Ich möchte mich lieber nicht um die Einstellung der Konfiguration in NUnit kümmern müssen. Wie kann ich mich biegen und drehen, um dies zu erreichen? :-)
MacGyver
3
Ich habe es herausgefunden ... Wenn Sie NUnit verwenden, benennen Sie Ihre app.config-Datei mit demselben Namen wie Ihren * .nunit-Projektdateinamen. Wenn Sie beispielsweise Ihr Projekt "ClassLibraryA.nunit" genannt haben, benennen Sie die Konfigurationsdatei Ihrer Klassenbibliothek "ClassLibraryA.config". Sie müssen sich auch im selben Ordner / Verzeichnis befinden. NUnit verwendet dies tatsächlich als Hauptkonfigurationsdatei. Fügen Sie einen Verweis auf System.Configuration (in der Registerkarte .NET) hinzu. Verwenden Sie diesen Code: string settingsValue = ConfigurationManager.AppSettings ["settingsName"];
MacGyver
2
Wie würden Sie die Einrichtung bei Integrationstests empfehlen? Für mich scheint es logisch, eine app.config in dieser Testbibliothek mit der Verbindungszeichenfolge zu haben.
Tomas Jansson
2
Was ist, wenn Sie die Anwendung nicht konfigurieren können, weil Sie sie nicht besitzen?
Spannungsspitze
50

Ich weiß nicht, warum diese Antwort noch nicht gegeben wurde:

Verschiedene Anrufer derselben Bibliothek verwenden im Allgemeinen unterschiedliche Konfigurationen. Dies bedeutet, dass sich die Konfiguration in der ausführbaren Anwendung und nicht in der Klassenbibliothek befinden muss.

Sie können eine app.config innerhalb des Klassenbibliotheksprojekts erstellen. Es enthält Standardkonfigurationen für Elemente, die Sie in der Bibliothek erstellen. Beispielsweise enthält es Verbindungszeichenfolgen, wenn Sie ein Entity Framework-Modell in der Klassenbibliothek erstellen.

Diese Einstellungen werden jedoch nicht von der ausführbaren Anwendung verwendet, die die Bibliothek aufruft. Stattdessen können diese Einstellungen aus der Datei library.dll.config in die Datei app.config oder web.config des Anrufers kopiert werden, sodass sie für den Anrufer und die Umgebung, in der sich der Anrufer befindet, geändert werden können bereitgestellt.

So ist es mit .NET seit Tag 1.

John Saunders
quelle
2
Aber was soll ich tun, wenn ich die Webserice-Funktionalität aus der Klassenbibliothek aufrufen muss? VS hat eine Standard-app.config erstellt, aber meine Anwendung ist abgestürzt, als sie versucht hat, die Webservice-Funktion aufzurufen - sie kann keine Konfigurationseinträge finden ...
Laserson
Sie müssen die Elemente, die in der Klassenbibliothek app.config platziert wurden, in die app.config oder web.config des Aufrufers der Klassenbibliothek kopieren. Dadurch hat der Anrufer die Kontrolle über die Konfiguration. Beispielsweise kann der Aufrufer jetzt die URL des Dienstes ändern, den Ihre Klassenbibliothek aufruft, und Ihre Klassenbibliothek weiß nicht einmal von der Änderung.
John Saunders
6
@ John Saunders: "Vielleicht brauchen" sind genau die richtigen Worte. Es kann also Situationen geben, in denen sich die Konfigurationseinstellungen nur pro Server unterscheiden (z. B. Verbindungszeichenfolgen) und es bequemer ist, die DLL über eine eigene Konfiguration zu verfügen, als sie für jede Assembly, die die DLL verwendet, mehrmals zu kopieren. Meiner Meinung nach ist die bevorzugte Verwendung von Microsoft / .NET kein heiliger Gral. Es hängt wirklich davon ab, was in einem Bereitstellungsszenario am bequemsten ist. Es ist nicht nötig, Todd zu verraten, seine Meinung ist genauso wichtig wie Ihre oder Microsoft.
Ich bin wirklich an dieser Lösung interessiert - sie klingt für mich ideal. Es ist sinnvoll, dass die Bibliothek Standardeinstellungen enthält, während die Anwendung diese überschreiben kann. Würden Sie erläutern, wie Einstellungen von der app.config der Bibliothek in die app.config der ausführenden Assembly übertragen werden können, oder mich zu einer relevanten Ressource weiterleiten?
Crush
@crush: Es heißt "Kopieren und Einfügen". Die stark typisierte Einstellungsfunktion von .NET kann ein wenig hilfreich sein, da Standardwerte in die Assembly gebacken werden.
John Saunders
42

Jon, es wurde eine Menge Meinungen abgegeben, die deine Frage nicht richtig beantwortet haben.

Ich werde MEINE MEINUNG geben und Ihnen dann sagen, wie Sie genau das tun sollen, wonach Sie gefragt haben.

Ich sehe keinen Grund, warum eine Assembly keine eigene Konfigurationsdatei haben könnte. Warum befindet sich die erste Ebene der Atomik (ist das ein echtes Wort?) Auf der Anwendungsebene? Warum nicht auf Lösungsebene? Es ist eine willkürliche Entscheidung nach bestem Wissen und als solche eine MEINUNG. Wenn Sie eine Protokollierungsbibliothek schreiben und eine Konfigurationsdatei dafür einschließen möchten, die global verwendet wird, warum können Sie sich dann nicht in die integrierten Einstellungsfunktionen einbinden? Wir haben es alle geschafft ... haben versucht, anderen Entwicklern "leistungsstarke" Funktionen zur Verfügung zu stellen. Wie? Indem wir Annahmen treffen, die von Natur aus zu Einschränkungen führen. Genau das hat MS mit dem Einstellungs-Framework gemacht, also müssen Sie es ein wenig "täuschen".

Um Ihre Frage direkt zu beantworten, fügen Sie die Konfigurationsdatei einfach manuell hinzu (xml) und benennen Sie sie so, dass sie mit Ihrer Bibliothek übereinstimmt und die Erweiterung "config" enthält. Beispiel:

MyDomain.Mylibrary.dll.Config

Verwenden Sie als Nächstes den ConfigurationManager, um die Datei zu laden und auf die Einstellungen zuzugreifen:

string assemblyPath = new Uri(Assembly.GetExecutingAssembly().CodeBase).AbsolutePath;
Configuration cfg = ConfigurationManager.OpenExeConfiguration(assemblyPath);
string result = cfg.AppSettings.Settings["TEST_SETTING"].Value;

Beachten Sie, dass dies die heierarchy machine.config vollständig unterstützt, obwohl Sie die App-Konfigurationsdatei explizit ausgewählt haben. Mit anderen Worten, wenn die Einstellung nicht vorhanden ist, wird sie höher aufgelöst. Die Einstellungen überschreiben auch die Einträge in machine.config.

Todd Beaulieu
quelle
3
-1: Ihre Meinung an sich ist nicht wichtig. Fakten wären wichtig. .NET wurde seit Tag 1 erstellt, damit die Aufrufer einer Bibliothek die Konfiguration der Elemente in der Bibliothek bestimmen. Dies ist das einzige, was für die Konfiguration tatsächlich Sinn macht, da unterschiedliche Aufrufer der Bibliothek möglicherweise unterschiedliche Konfigurationen benötigen.
John Saunders
18
@JohnSaunders "Unterschiedliche Aufrufer der Bibliothek benötigen möglicherweise unterschiedliche Konfigurationen." Genau, sie "können" unterschiedliche Konfigurationen benötigen, und Ihre Logik ist in allen Fällen, in denen die Konfiguration vom Anrufer abhängt, absolut sinnvoll. Es gibt jedoch mehrere Fälle, in denen die Konfiguration intern für die Klassenbibliothek verwendet wird und die Konfiguration unabhängig vom Aufrufer genau dieselbe ist. Wenn Sie 10 Anwendungen haben, die eine Bibliothek verbrauchen, muss es schlimmer sein, genau dieselbe Konfiguration zu kopieren und in 10 Konfigurationsdateien einzufügen.
Wired_in
3
@ToddBeaulieu: Ich denke, das Wort, das Sie wollen, ist "Atomizität".
nicodemus13
3
In einer Plugin-Architektur ist es in der Tat sinnvoll, wenn alle Plugins eine eigene Konfigurationsdatei haben.
Davatar
4
@RMuesi Niemand sagte, dass es sich nie ändert, nur dass es nicht vom Aufrufer der Bibliothek abhängt. Die Konfiguration kann sich ändern, je nachdem, ob Sie die Bibliothek im Vergleich zu einer Produktionsversion debuggen. Es kann sich abhängig von der Umgebung ändern, für die Sie bauen usw.
wired_in
6

Tatsächlich ruft die Klassenbibliothek, die Sie implementieren, Informationen aus app.config in der Anwendung ab, die sie verbraucht. Die korrekteste Methode zum Implementieren der Konfiguration für Klassenbibliotheken bei .net in VS besteht darin, app.config in der Datei vorzubereiten Anwendung, um alles zu konfigurieren, was es verbraucht, wie die Konfiguration von Bibliotheken.

Ich habe ein wenig mit log4net gearbeitet und festgestellt, dass derjenige, der die Anwendung vorbereitet hat, immer einen Abschnitt für die log4net-Konfiguration in der Haupt- app.config hatte .

Ich hoffe, Sie finden diese Informationen hilfreich.

Wir sehen uns und veröffentlichen Kommentare zu der gefundenen Lösung.

BEARBEITEN:

Unter dem nächsten Link haben Sie eine app.config mit dem Abschnitt für log4net:

http://weblogs.asp.net/tgraham/archive/2007/03/15/a-realistic-log4net-config.aspx

Amedio
quelle
2
+1 genau; Das app.configwird aus dem eigentlichen Programm geladen, das schließlich ausgeführt wird ... nicht aus den einzelnen Klassenbibliotheken. Es ist ehrlich gesagt ein bisschen verwirrend, wie viele diese sehr grundlegende Tatsache nicht kennen.
Andrew Barber
Vielleicht kommen Leute aus der Java-Sprache und dort haben Sie eine log4java.properties und eine separate Eigenschaftendatei für Ihre Anwendung.
Amedio
6

Wenn Sie Ihre Projektprotokollierung mit log4Net konfigurieren möchten, während Sie eine Klassenbibliothek verwenden, ist keine Konfigurationsdatei erforderlich. Sie können Ihren log4net-Logger in einer Klasse konfigurieren und diese Klasse als Bibliothek verwenden.

Als log4net bietet alle Optionen, um es zu konfigurieren.

Den Code finden Sie unten.

public static void SetLogger(string pathName, string pattern)
        {
            Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();

            PatternLayout patternLayout = new PatternLayout();
            patternLayout.ConversionPattern = pattern;
            patternLayout.ActivateOptions();

            RollingFileAppender roller = new RollingFileAppender();
            roller.AppendToFile = false;
            roller.File = pathName;
            roller.Layout = patternLayout;
            roller.MaxSizeRollBackups = 5;
            roller.MaximumFileSize = "1GB";
            roller.RollingStyle = RollingFileAppender.RollingMode.Size;
            roller.StaticLogFileName = true;
            roller.ActivateOptions();
            hierarchy.Root.AddAppender(roller);

            MemoryAppender memory = new MemoryAppender();
            memory.ActivateOptions();
            hierarchy.Root.AddAppender(memory);

            hierarchy.Root.Level = log4net.Core.Level.Info;
            hierarchy.Configured = true;
      }

Anstatt XmlConfigurator.Configure (neues FileInfo ("app.config")) aufzurufen, können Sie jetzt SetLogger mit dem gewünschten Pfad und Muster direkt aufrufen, um den Logger in der Startfunktion der Global.asax-Anwendung festzulegen.

Verwenden Sie den folgenden Code, um den Fehler zu protokollieren.

        public static void getLog(string className, string message)
        {
            log4net.ILog iLOG = LogManager.GetLogger(className);
            iLOG.Error(message);    // Info, Fatal, Warn, Debug
        }

Wenn Sie den folgenden Code verwenden, müssen Sie weder in der Anwendung web.config noch in der app.config der Bibliothek eine einzelne Zeile schreiben.

Rahul
quelle
2
Ich fand, dass dies die beste Antwort ist ... anstatt zu diskutieren, ob eine Konfigurationsdatei für eine Bibliothek zulässig sein sollte ... Diese Antwort beantwortet die Frage des OP nach der Verwendung von Log4net
saurav
1
Obwohl in der Frage log4net als Beispiel verwendet wurde, handelt es sich bei der eigentlichen Frage um Konfigurationen im Allgemeinen. Ich würde sagen, dass Antworten zu log4net eigentlich irrelevant sind.
Binki
4

In einigen seltenen Fällen können Sie app.config in Klassenbibliotheken speichern (durch manuelles Hinzufügen) und durch OpenExeConfiguration analysieren .

 var fileMap =
    new ExeConfigurationFileMap {ExeConfigFilename = 
    @"C:\..somePath..\someName.config"};
 System.Configuration.Configuration config =
    ConfigurationManager.OpenMappedExeConfiguration(fileMap, 
    ConfigurationUserLevel.None);

Sie sollten den tatsächlichen Bedarf wirklich einschätzen. Für abstrakte Daten ist es nicht die beste Lösung, aber "Config Sections" könnte sehr nützlich sein !!

Zum Beispiel haben wir unsere N-Tier-WCF-Architektur ohne Metadaten einfach mithilfe von Unity Container und Injection Factory basierend auf Channel Factory T entkoppelt. Wir haben die externe ClassLibrary-DLL mit nur [Service Contract] -Schnittstellen und der gemeinsamen app.config in der angegebenen Reihenfolge hinzugefügt um Endpunkte aus dem Client-Bereich zu lesen und sie einfach an einer Stelle hinzuzufügen / zu ändern.

Roma Borodov
quelle
3

Sie möchten hinzufügen App.config in Ihre Tests Klassenbibliothek, wenn Sie einen Tracer / Logger verwenden. Andernfalls wird nichts protokolliert, wenn Sie den Test über einen Testläufer wie TestDriven.Net ausführen.

Zum Beispiel verwende ich TraceSourcein meinen Programmen, aber das Ausführen von Tests protokolliert nichts, es sei denn, ich füge der Testklassenbibliothek auch eine App.config- Datei mit der Trace- / Protokollkonfiguration hinzu.

Andernfalls führt das Hinzufügen von App.config zu einer Klassenbibliothek nichts aus.

Daniel AA Pelsmaeker
quelle
2

Ihre Antwort für eine nicht manuelle Erstellung einer app.config lautet die Registerkarte Eigenschaften / Einstellungen von Visual Studio-Projekt.

Wenn Sie eine Einstellung hinzufügen und speichern, wird Ihre app.config automatisch erstellt. Zu diesem Zeitpunkt wird eine Reihe von Code in einem Namespace { yourclasslibrary .Properties} generiert , der Eigenschaften enthält, die Ihren Einstellungen entsprechen. Die Einstellungen selbst werden in den applicationSettings-Einstellungen der app.config gespeichert.

 <configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
        <section name="ClassLibrary.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
</configSections>
<applicationSettings>
    <ClassLibrary.Properties.Settings>
        <setting name="Setting1" serializeAs="String">
            <value>3</value>
        </setting>
    </BookOneGenerator.Properties.Settings>
</applicationSettings>

Wenn Sie eine Einstellung mit Anwendungsbereich mit dem Namen "Einstellung1 = 3" hinzugefügt haben, wird eine Eigenschaft mit dem Namen "Einstellung1" erstellt. Diese Eigenschaften werden beim Kompilieren Teil der Binärdatei und werden mit einem DefaultSettingValueAttribute dekoriert, das auf den Wert festgelegt wird, den Sie zur Entwicklungszeit angegeben haben.

     [ApplicationScopedSetting]
    [DebuggerNonUserCode]
    [DefaultSettingValue("3")]
    public string Setting1
    {
        get
        {
            return (string)this["Setting1"];
        }
    }

Wenn Sie also wie in Ihrem Klassenbibliothekscode diese Eigenschaften verwenden, wird in der Laufzeitkonfigurationsdatei keine entsprechende Einstellung verwendet, um den Standardwert zu verwenden. Auf diese Weise stürzt die Anwendung nicht ab, weil ein Einstellungseintrag fehlt. Dies ist beim ersten Mal sehr verwirrend, wenn Sie nicht wissen, wie diese Dinge funktionieren. Nun fragen Sie sich, wie Sie unseren eigenen neuen Wert in einer bereitgestellten Bibliothek angeben und vermeiden können, dass der Standardeinstellungswert verwendet wird.

Dies geschieht, wenn wir die app.config der ausführbaren Datei ordnungsgemäß konfigurieren. Zwei schritte. 1. Wir machen darauf aufmerksam, dass wir einen Einstellungsabschnitt für diese Klassenbibliothek haben werden. 2. Mit kleinen Änderungen fügen wir die Konfigurationsdatei der Klassenbibliothek in die ausführbare Konfiguration ein. (Es gibt eine Methode, mit der Sie die Konfigurationsdatei der Klassenbibliothek extern halten und sie einfach aus der Konfiguration der ausführbaren Datei referenzieren können.

Sie können also eine app.config für eine Klassenbibliothek haben, diese ist jedoch nutzlos, wenn Sie sie nicht ordnungsgemäß in die übergeordnete Anwendung integrieren. Sehen Sie hier, was ich vor einiger Zeit geschrieben habe: Link

Mircea Ion
quelle
1

Wenn Sie Ihrer Lösung ein Klassenbibliotheksprojekt hinzufügen, wird die Datei app.config nicht automatisch hinzugefügt.

Meines Wissens gibt es keine Gegenanzeige dafür. Ich denke, das ist eine häufige Verwendung.

In Bezug auf die log4Net-Konfiguration müssen Sie die Konfiguration nicht in app.config ablegen. Sie können gleichzeitig eine dedizierte conf-Datei in Ihrem Projekt sowie eine app.config-Datei haben.

Dieser Link http://logging.apache.org/log4net/release/manual/configuration.html enthält Beispiele für beide Möglichkeiten (Abschnitt in app.config und eigenständige log4net conf-Datei).

Bruno
quelle
Es tut nichts weh app.config, einem Bibliotheksprojekt ein hinzuzufügen , nein. Aber es wird auch nicht verwendet.
Andrew Barber
1
@ AndrewBarber Es wird in einem Testprojekt verwendet. Siehe stackoverflow.com/a/31389495
binki
0

Ich würde empfehlen, Properties.Settings zu verwenden, um Werte wie ConnectionStrings usw. in der Klassenbibliothek zu speichern. Hier werden alle Verbindungszeichenfolgen auf Vorschlag von Visual Studio gespeichert, wenn Sie beispielsweise versuchen, einen Tabellenadapter hinzuzufügen. Geben Sie hier die Bildbeschreibung ein

Und dann können Sie mit diesem Code überall in der Klassenbibliothek darauf zugreifen

var cs=  Properties.Settings.Default.[<name of defined setting>];
Sishanov
quelle