it-swarm.com.de

Benutzerdefinierte Konfigurationsdatei in C # lesen (Framework 4.0)

Ich entwickle eine Anwendung in C # unter Framework 4.0.

In meiner Anwendung möchte ich eine separate Konfigurationsdatei erstellen, die nicht die Datei app.config ist. Die Konfigurationsdatei enthält benutzerdefinierte Konfigurationsabschnitte, die wir für das Produkt entwickelt haben.

Ich möchte diese Datei nicht aus der app.config mit der configSource referenzieren. 

Ich möchte es zur Laufzeit laden und seinen Inhalt lesen.

Ein Beispiel für das, was ich meine, ist log4net, mit dem Sie die Konfiguration in die Datei log4net.config schreiben können.

Kann jemand helfen, wie das geht, ohne Code zu schreiben, der den im Framework vorhandenen Code nachahmt?

UPDATE:

basierend auf der Antwort von Kaido Ich habe eine Utility-Klasse geschrieben, die die benutzerdefinierte Konfigurationsdatei liest und die Möglichkeit hat, den Config-Inhalt zu aktualisieren, wenn sich die Datei im Dateisystem ändert.

Die Verwendung in dieser Klasse ist wie folgt:

  1. Rufen Sie den Inhalt der Konfigurationsdatei ab

    // Create configuration reader that reads the files once
    var configFileReader = new CustomConfigurationFileReader("c:\\myconfig.config");
    var config = configFileReader.Config;
    
    // Do any action you want with the config object like:
    config.GetSection("my.custom.section");
    
    // or,
    var someVal = config.AppSettings.Settings["someKey"];
    
  2. Erhalten Sie Benachrichtigungen, wenn sich die Konfigurationsdatei ändert

    // Create configuration reader that notifies when the configuraiton file changes
    var configFileReader = new CustomConfigurationFileReader("c:\\myconfig.config", true);
    
    // Register to the FileChanged event
    configFileReader.FileChanged += MyEventHandler;
    
    ...
    
    private void MyEventHanler(object sender, EventArgs e)
    {
         // You can safely access the Config property here, it is already contains the new content
    }
    

In dem Code habe ich PostSharp verwendet, um den Konstruktor-Eingabeparameter zu überprüfen, um sicherzustellen, dass die Protokolldatei nicht null ist und dass die Datei vorhanden ist. Sie können den Code ändern, um diese Überprüfung im Code inline zu machen (obwohl ich empfehle, PostSharp zu verwenden, um die Anwendung nach Aspekten zu trennen).

Hier ist der Code:

    using System;
    using System.Configuration;
    using System.IO;
    using CSG.Core.Validation;

    namespace CSG.Core.Configuration
    {
        /// <summary>
        /// Reads customer configuration file
        /// </summary>
        public class CustomConfigurationFileReader
        {
            // By default, don't notify on file change
            private const bool DEFAULT_NOTIFY_BEHAVIOUR = false;

            #region Fields

            // The configuration file name
            private readonly string _configFileName;

            /// <summary>
            /// Raises when the configuraiton file is modified
            /// </summary>
            public event System.EventHandler FileChanged;

            #endregion Fields

            #region Constructor

            /// <summary>
            /// Initialize a new instance of the CustomConfigurationFileReader class that notifies 
            /// when the configuration file changes.
            /// </summary>
            /// <param name="configFileName">The full path to the custom configuration file</param>
            public CustomConfigurationFileReader(string configFileName)
                : this(configFileName, DEFAULT_NOTIFY_BEHAVIOUR)
            {            
            }        

            /// <summary>
            /// Initialize a new instance of the CustomConfigurationFileReader class
            /// </summary>
            /// <param name="configFileName">The full path to the custom configuration file</param>
            /// <param name="notifyOnFileChange">Indicate if to raise the FileChange event when the configuraiton file changes</param>
            [ValidateParameters]
            public CustomConfigurationFileReader([NotNull, FileExists]string configFileName, bool notifyOnFileChange)
            {
                // Set the configuration file name
                _configFileName = configFileName;

                // Read the configuration File
                ReadConfiguration();

                // Start watch the configuration file (if notifyOnFileChanged is true)
                if(notifyOnFileChange)
                    WatchConfigFile();
            }

            #endregion Constructor        

            /// <summary>
            /// Get the configuration that represents the content of the configuration file
            /// </summary>
            public System.Configuration.Configuration Config
            {
                get;
                set;
            }

            #region Helper Methods

            /// <summary>
            /// Watch the configuraiton file for changes
            /// </summary>
            private void WatchConfigFile()
            {
                var watcher = new FileSystemWatcher(_configFileName);
                watcher.Changed += ConfigFileChangedEvent;
            }

            /// <summary>
            /// Read the configuration file
            /// </summary>
            public void ReadConfiguration()
            {
                // Create config file map to point to the configuration file
                var configFileMap = new ExeConfigurationFileMap
                {
                    ExeConfigFilename = _configFileName
                };

                // Create configuration object that contains the content of the custom configuration file
                Config = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
            }        

            /// <summary>
            /// Called when the configuration file changed.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void ConfigFileChangedEvent(object sender, FileSystemEventArgs e)
            {
                // Check if the file changed event has listeners
                if (FileChanged != null)
                    // Raise the event
                    FileChanged(this, new EventArgs());
            }

            #endregion Helper Methods
        }
    }
37
Koby Mizrahy
 // Map the roaming configuration file. This
      // enables the application to access 
      // the configuration file using the
      // System.Configuration.Configuration class
      ExeConfigurationFileMap configFileMap =
        new ExeConfigurationFileMap();
      configFileMap.ExeConfigFilename = 
        roamingConfig.FilePath;

      // Get the mapped configuration file.
      Configuration config =
        ConfigurationManager.OpenMappedExeConfiguration(
          configFileMap, ConfigurationUserLevel.None);

von http://msdn.Microsoft.com/de-de/library/system.configuration.configurationmanager.aspx

18
Kaido

In der Vergangenheit habe ich Nini - http://nini.sourceforge.net/manual.php verwendet, mit dem Sie benutzerdefinierte Konfigurationsdateien (XML/Ini/Registry/.Config) zur Laufzeit lesen/schreiben können.

Hoffe das hilft.

6
christofr

Mein Rat bei der Konfiguration ist, eine eigene Komponente zum Lesen zu erstellen.
Es kann die Entwicklung erleichtern, wenn Sie irgendwann entscheiden, dass Sie die Konfiguration von einer anderen Quelle wie einer Datenbank oder über einen Webdienst erhalten.
Diese Art der Abstraktion hilft Ihnen auch, die Konfiguration zu verspotten und erhöht die Testbarkeit (etwas, was das .NET-Framework überhaupt nicht gut macht).
Wenn Sie XML als Konfigurationsformat verwenden, empfehle ich die Verwendung von Linq to XML.
Es ist einfacher zu lesen und zu verwenden, um XML-Dateien zu parsen.

2
the_drow

Sie können Cinchoo Framework für Ihre Bedürfnisse ausprobieren. Es vereinfacht die Entwicklungsarbeit durch den Code-First-Ansatz. Definieren Sie eine Klasse wie folgt:

namespace HelloWorld
{
    #region NameSpaces

    using System;
    using Cinchoo.Core.Configuration;

    #endregion NameSpaces

    [ChoConfigurationSection("sample")]
    public class SampleConfigSection : ChoConfigurableObject
    {
        #region Instance Data Members (Public)

        [ChoPropertyInfo("name", DefaultValue="Mark")]
        public string Name;

        [ChoPropertyInfo("message", DefaultValue="Hello World!")]
        public string Message;

        #endregion
    }

    static void Main(string[] args)
    {
        SampleConfigSection sampleConfigSection = new SampleConfigSection();
        Console.WriteLine(sampleConfigSection.ToString());
    }

}

Wenn Sie die Anwendung zum ersten Mal ausführen, wird der Konfigurationsabschnitt in der Datei [Anwendungsname] .xml wie folgt erstellt. Danach werden alle an dieser Datei vorgenommenen Änderungen automatisch übernommen 

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="sample" type="Cinchoo.Core.Configuration.ChoNameValueSectionHandler, Cinchoo.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7dacd80ff3e33de" />
  </configSections>
  <sample>
    <add key="name" value="Mark" />
    <add key="message" value="Hello World!" />
  </sample>
</configuration>
2
nittuj

Oder benutze NameValueCollection einfacher 

0
Damian