We use cookies for keeping user sessions alive and for site usage statistics.
Please accept cookies to continue browsing the site.

 

(You can decline cookies later navigating to page 'Privacy Policy'.)

Custom application settings file


Sometimes you want to get rid of those settings kept in the traditional web.config or app.config file. You want more fine grained control over the deployment of your settings entries and separated data design. Or the requirement is to enable adding new entries at runtime.

Here are two very short, but fully functional implementations:

  • The strongly typed version and
  • The object oriented version.

Let's start with the strongly typed version. The advantage here are the strongly typed settings names and values. There is no risk of intermixing names or data types. The disadvantage is that more settings have to be coded, cannot be added at runtime.

using System;
using System.Text;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.Serialization;

namespace Common
{
    public class AppSettings
    {
        public static readonly string SettingsFilePath = new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName + @"\AppSettings.xml";

        #region Get/Set 
        public static int GetSetting1() {
            var appSettings = LoadAppSettings();
            return appSettings.Setting1;
        }
        public static void SetSetting1(int value) {
            var appSettings = LoadAppSettings();
            appSettings.Setting1 = value;
            SaveAppSettings(appSettings);
        }

        public static bool GetSetting2() {
            var appSettings = LoadAppSettings();
            return appSettings.Setting2;
        }
        public static void SetSetting2(bool value) {
            var appSettings = LoadAppSettings();
            appSettings.Setting2 = value;
            SaveAppSettings(appSettings);
        }

        public static string GetSetting3() {
            var appSettings = LoadAppSettings();
            return appSettings.Setting3;
        }
        public static void SetSetting3(string value) {
            var appSettings = LoadAppSettings();
            appSettings.Setting3 = value;
            SaveAppSettings(appSettings);
        }
        #endregion 

        #region Load/Save settings
        static Settings LoadAppSettings() {
            var fiFile = new FileInfo(SettingsFilePath);
            if (!fiFile.Exists || fiFile.Length <= 3) { // UTF-8 preamble.
                return new Settings();
            }

            using (var reader = new XmlTextReader(SettingsFilePath)) {
                return (Settings)new XmlSerializer(typeof(Settings)).Deserialize(reader);
            }
        }

        static void SaveAppSettings(Settings appSettings){
            using (var writer = new XmlTextWriter(SettingsFilePath, Encoding.UTF8)) {
                writer.Formatting = Formatting.Indented;
                new XmlSerializer(typeof(Settings)).Serialize(writer, appSettings);
            }
        }
        #endregion

        #region Settings helper class
        public class Settings
        {
            public int Setting1 { get; set; }
            public bool Setting2 { get; set; }
            public string Setting3 { get; set; }
        }
        #endregion
    }
}

Usage pattern:

nt test = AppSettings.GetSetting1(); 
AppSettings.SetSetting1(100);

And now let's have a look at the object oriented version. Here the advantage is that new settings can be added at runtime. But you do not have strongly typed names and values. Must be careful with string identifiers. Must know data type saved earlier when getting a value.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.Serialization;

namespace Common
{
    public static class AppSettings
    {
        public static readonly string SettingsFilePath = new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName + @"\AppSettings.xml";

        #region Get setting
        public static object Get(string key) {
            var fiFile = new FileInfo(SettingsFilePath);
            if (!File.Exists(SettingsFilePath) || fiFile.Length <= 3) { // UTF-8 preamble.
                throw new KeyNotFoundException("Key not found: " + key);
            }

            using (var reader = new XmlTextReader(SettingsFilePath)) {
                var settings = (List<Setting>)new XmlSerializer(typeof(List<Setting>)).Deserialize(reader);
                var setting = settings.SingleOrDefault(s => s.Key.Equals(key, StringComparison.InvariantCultureIgnoreCase));
                if (setting != null) {
                    return setting.Value;
                }
                else {
                    throw new KeyNotFoundException("Key not found: " + key);
                }
            }
        }
        #endregion

        #region Set setting
        public static void Set(string key, object value) {
            List<Setting> settings;

            // Get list.
            var fiFile = new FileInfo(SettingsFilePath);
            if (!File.Exists(SettingsFilePath) || fiFile.Length <= 3) { // UTF-8 preamble.
                settings = new List<Setting>();
            }
            else {
                using (var reader = new XmlTextReader(SettingsFilePath)) {
                    settings = (List<Setting>)new XmlSerializer(typeof(List<Setting>)).Deserialize(reader);
                }
            }

            // Update item.
            var setting = settings.SingleOrDefault(s => s.Key.Equals(key, StringComparison.InvariantCultureIgnoreCase));
            if (setting != null) {
                setting.Value = value;
            }
            else {
                settings.Add(new Setting { Key = key, Value = value});
            }

            // Save list.
            using (var writer = new XmlTextWriter(SettingsFilePath, Encoding.UTF8)) {
                writer.Formatting = Formatting.Indented;
                new XmlSerializer(typeof(List<Setting>)).Serialize(writer, settings);
            }
        }
        #endregion

        #region Setting helper class
        public class Setting
        {
            public string Key;
            public object Value;
        }
        #endregion
    }

    #region Exceptions
    public class KeyNotFoundException : ApplicationException{
        public KeyNotFoundException() {
        }

        public KeyNotFoundException(string message) : base(message){
        }
    }
    #endregion
}

Usage pattern:

int test = (int)AppSettings.Get("setting1");
AppSettings.Set("setting1", 100);

Enjoy your choice!


Back to List