6
\$\begingroup\$

I have a WPF app and a bunch of read/write settings that need to be accessible from various view models. a setting can be any type (string, bool, etc) and all are settable, but only from a 'Settings' view. I also need the view models to be notified when any setting has been updated and which one that was.

Here is an enum with all the settings:

public enum Setting
{
    SettingA,
    SettingB,
    //etc 
}

here is the settings class, as a singleton:

  internal sealed class Settings
{
    private static volatile Settings _instance;
    private static object _syncRoot = new object();
    private Dictionary<Setting, object> _settings;

    private Settings()
    {
        _settings = new Dictionary<Setting, object>();
        _settings.Add(Setting.SettingA, 1000);
        _settings.Add(Setting.SettingB, 1000);    
    }

    public static Settings Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (_syncRoot)
                {
                    if (_instance == null)
                    {
                        _instance = new Settings();
                    }
                }
            }
            return _instance;
        }
    }

    public void UpdateSetting(Setting key, object value)
    {
        if (_settings[key] != value)
        {
            _settings[key] = value;
            TriggerNotification(key, value);
        }
    }

    public T GetSetting<T>(Setting key)
    {
        return (T)_settings[key];
    }

    public event EventHandler<SettingsUpdatedEventArgs> OnSettingsUpdated;

    private void TriggerNotification(Setting key, object value)
    {
        var handler = OnSettingsUpdated;
        if (handler != null)
        {
            handler(this, new SettingsUpdatedEventArgs(key, value));
        }
    }
}

here is the overrided event args:

 public class SettingsUpdatedEventArgs : EventArgs
{
    public Setting Type { get; private set; }
    public object Value { get; private set; }

    public SettingsUpdatedEventArgs(Setting type, object value)
    {
        Type = type;
        Value = value;
    }
}

and here is how it is used:

    //update a setting value
    Settings.Instance.UpdateSetting(Setting.SettingA,200);


    //retrieve a setting value
    var value = Settings.Instance.GetSetting<int>(Setting.SettingA);

    //register a listener
    Settings.Instance.OnSettingsUpdated += (sender, args) =>
    {
        if (args.Type == Setting.SettingA)
        {
            var result = args.Value;
        }

    };

and now my questions:

  • Is there a problem having the settings class as a singleton?
  • Is this a type-safe way to get the setting values?
  • Is there a much better/simpler/more elegant way of doing this?
\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to Code Review! This is a very nice question. You maybe also want to check out our Code Review Chat ;) \$\endgroup\$ – Vogel612 May 18 '14 at 14:01
  • \$\begingroup\$ Very relevant to me right now. I've been struggling with a similar piece of code. Welcome to CR. \$\endgroup\$ – RubberDuck Jan 3 '15 at 14:04
2
\$\begingroup\$

Is this a type-safe way to get the setting values?

It's not type-safe in the sense that if you make a mistake in specifying the type parameter of GetSetting, or if someone sets setting to the wrong type, you're going to get an exception.

I've struggled with this issue before and I have created a solution to this that uses generic keys. It's by no means perfect, but you can use it as an inspiration.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ awesome, I did something similar now! type safety done right :) \$\endgroup\$ – Balanikas May 18 '14 at 16:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.