views:

52

answers:

4

I am writing a program that need to store some configuration information. I thought XML would be a good choice, but I do not want to learn XML in C# from scratch.

Could you recommend good ways/classes handling this task?

+6  A: 

Just use the built-in .NET configuration system! What's wrong with that??

For that, add a reference to System.Configuration to your project, and have a good look at the ConfigurationManager class in that namespace.

Starting with Visual Studio 2005, you can also define application- or user-scoped settings in a visual designer inside VS - check out Application Settings Overview on MSDN for this (those work for Winforms and console apps). Those settings are stored in your app.config/web.config for the application-scoped settings, and in a separate user.config file in a directory accessible to the user account for the user-scoped settings. Those can be manipulated and updated at runtime using standard .NET classes (from the System.Configuration namespace).

marc_s
Agreed. Why must people re-invent the wheel?
RPM1984
Could I update the settings later?
Jichao
@Jiacho: you can **always** edit the *.config file, of course. Also: Visual Studio has a "Settings" node in its projects - those are stored in the .NET configuration system, too, and you can have application-wide settings, and user-specific settings, which can be updated at runtime, no problem
marc_s
A: 

While I agree that "re-inventing the wheel" is not a good idea, the .NET System.Configuration class is abominably difficult to use for such a simple task.

I needed to create separate configuration files that could be specified on the command line for one of my programs (instead of just default assuming it would be "app.config") so I used this simple class - which saves itself to an XML file.

http://www.dot-dash-dot.com/files/UIsettings.vb

Ron Savage
The only thing that's difficult about using the built-in settings tools is when you want to do something they don't support out of the box and then you have to understand how they work. Until that point, it's hard to imagine how a settings system could be easier.
Robert Rossney
A: 

Here's a simple little snippet to get you started. You don't need to know any xml...

    internal static string GetConfigSetting(string settingName)
    {
        return ConfigurationManager.AppSettings[settingName].ToString();
    }

    internal static bool GetConfigSettingBool(string settingName)
    {
        string setting = GetConfigSetting(settingName);
        if (string.IsNullOrEmpty(setting)) return false;
        bool value = false;
        if (bool.TryParse(setting, out value))
            return value;
        else
            return false;
    }

    internal static string[] GetConfigSettingsArray(string settingName)
    {
        return GetConfigSetting(settingName).Split(',');
    }

    internal static DateTime? GetConfigSettingDateTime(string settingName)
    {
        string setting = GetConfigSetting(settingName);
        DateTime retval;
        if (DateTime.TryParse(setting, out retval))
        {
            return retval;
        }
        else
        {
            return null;
        }
    }

    internal static void SetConfigSetting(string settingName, string value){
        ConfigurationManager.AppSettings[settingName] = value;
    }
Jamie
A: 

I've been using an XML configuration type setup for some time now, which is run off the built in configuration, which is sort of neat. Basically, you can give it a hint, and it'll deserialize the xml right into an object for you. I think the original source I got this from was here, but i'm not 100% sure, so if someone does know the author, please edit my reply to give proper credit.

Here's the class that actually does the deserialization:

using System.Configuration;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.XPath;

namespace Ariel.Configuration
{
    class XmlSerializerSectionHandler : IConfigurationSectionHandler
    {
        public object Create(object parent, object configContext, XmlNode section)
        {
            XPathNavigator nav = section.CreateNavigator();
            string typename = (string)nav.Evaluate("string(@type)");
            Type t = Type.GetType(typename);
            XmlSerializer ser = new XmlSerializer(t);
            return ser.Deserialize(new XmlNodeReader(section));
        }
    }
}

Now, you can create any class you want for configuration.

namespace MyProject.Config {
    public class TestConfig {
        /// <summary>
        /// Whether the session is enabled
        /// </summary>
        public bool Enabled { get; set; }
    }
}

Now, all you need is an app.config file. I generally prefer a style to use a separate configuration file for each configuration class, so I'll give you that as an example.

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="TestConfig" type="Ariel.Configuration.XmlSerializerSectionHandler, Ariel"/>
  </configSections>
  <runtime>
    <gcServer enabled="true"/>
  </runtime>

  <TestConfig configSource="Config\\TestConfig.config" />
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

The Important parts are: section name = "TestConfig" <- The configuration class type=Ariel.Configuration.XmlSerializerSectionHandler, Ariel <- The type which is used to deserialize are xml in an object. This basically tells the configuration manager what to run to create our object TestConfig configSource="Config\TestConfig.config" <- This tells us where to find the configuration file for the section TestConfig.

In you're TestConfig.config file you would have something like this:

<?xml version="1.0" encoding="utf-8" ?>
<TestConfig type="MyProject.Config.TestConfig, MyProject">
  <Enabled>True</Enabled>
</TestConfig>

Again the important part is the reference to the class name and the Type.

Last but not least, to load you're configuration:

using System.Configuration;
Config.SessionKillConfig config = null;
try {
    config = (Config.SessionKillConfig)ConfigurationManager.GetSection("CdrAnalyzerConfig");
} catch (System.Configuration.ConfigurationException ex) {
    syslog.Fatal("Loading parser configuration failed", ex);
    return;
}

if(config.Enabled) { //do stuff }

This may be a little long winded, but the thing is, it's quite portable. Basically, to include configuration, all you have to do is write a class, and then write an xml file that matches that.

I'm not 100% sure how to pass the configuration file as an parameter to the program, but I imagine there is an option in the ConfigurationManager class somewhere for that. I even think I read somewhere that someone was working on having it detect changes to the file and reload new configuration into the running program, but I haven't tried anything like that. Anyways, I hope the example is useful for one approach you can take.

Kevin Nisbet