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\$
2
  • 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
    Commented May 18, 2014 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
    Commented Jan 3, 2015 at 14:04

1 Answer 1

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.

\$\endgroup\$
1
  • \$\begingroup\$ awesome, I did something similar now! type safety done right :) \$\endgroup\$ Commented May 18, 2014 at 16:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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