How to create a global settings object using singleton and hashtable

Posted on 2006-06-05
Last Modified: 2012-05-05

I'm trying to create an object called Settings that will store a set of values to be used throughout my application as well as read and write them in the registry.  So far I've defined a singleton called clsSettings with the following attributes:

public string RegistryPath //set this property to determine where the values are stored in the registry
public Hashtable Values //key-value pair where the key is the name of the setting (eg. "InputDir") and value is the value of that setting (eg. "C:\test")

public static GetInstance //Returns the persistent instance of my singleton clsSettings object
public bool Read (string default) //iterates through Values and looking for each Key in RegistryPath and assigning it to Value (not yet implemented)
public bool Write //iterates through Values and writes each Key to RegistryPath creating registry keys as necessary (not yet implemented)

I have a few questions:

1) Is this the best design for what I'm trying to do?
2) What's the easiest way to pull a value out of a hashtable?
3) Ideally, I would like to access my values like this:  Settings.Values["InputDir"] = "c:\test".  Is there an existing way for me to do this or would I have to build my own?
4) Do I have to explicitly destroy my singleton?

As you can tell I'm new to C# and appreciate any help you can offer.  :)

Question by:bussd
    LVL 25

    Accepted Solution

    1) "best" is up to you.  using a singleton is an acceptable method of doing this.

    One thing to change would be to make the variables private and create Get accessors:

    private string _RegistryPath; //set this property to determine where the values are stored in the registry
    public string RegistryPath {get {return _RegistryPath; } }

    private Hashtable _Values //key-value pair where the key is the name of the setting (eg. "InputDir") and value is the value of that setting (eg. "C:\test")
    public Hashtable Values {get {return _Values; } }

    That way you can't change the value of the Registrypath or change the Hashtable instance (you can read to/write from the hashtable, though).

    2) object value = Values["{key}"];

    3)  Settings.Values["InputDir"] = "c:\test".  This is not the proper way to use a singleton class.  You can use the following syntax:

    Settings settings = Settings.GetInstance();
    settings.Values["InputDir"] = "c:\test";

    Or shorten to one line:

    Settings.GetInstance().Values["InputDir"] = "c:\test";
    4) Unless you're using unmanaged or disposable resources (file handles, DB Connections, etc.) you don't need to explicitly dispose of your object.  If you are, use the Disposable pattern (especially since the instance will be shared).

    Author Comment

    Thanks for the quick response!

    Is there a way to store data of different types in my hashtable, or am I limited to strings?

    Also, being new to C#/.NET I'm not sure what you mean by unmanaged resources.  Please explain?
    LVL 25

    Expert Comment

    The hashtable stores everything as an Object, ou can store any type, but you'll have to cast it back when you retrieve it:

    int intValue = (int)hashtable["key1"];
    string stringValue = (string)hashtable["key2"];

    etc.  As long as you know what type it is, you can directly cast it.  If the types aren't compatible, you will get an InvalidCastException.

    unmanaged resources are things like File Handles, COM object pointers, etc.  If you're just using basic types (int, string, bool), or .NET classes, you con't need to explicitly dispose of the singleton.

    Author Comment

    It seems like I can't assign anything to Values ("NullReferenceexception was unhandled").  Do I need a set accessor for my _Values property?  If so, what would that look like?
    LVL 25

    Expert Comment

    For a singleton class you should assign in in the private constructor:

    private Settings()
      this._Values = new Hashtable();
      this._RegistryPath = {set value};

    You generally don't have set accessors for singleton properties because you run into issues of what is responsible for setting the value.  Singletons should generally have the same values across all instances (that's why it's a singleton).

    Author Comment

    I can now assign values (thanks!), but I'm confused about this:

    > You generally don't have set accessors for singleton properties because you run into issues of what is responsible for setting the value.

    Doesn't using the GetInstance() method prevent multiple instances?  If so then how could you have different values for the same property/variable?

    I would like to set RegistryPath from outside the class (eg. clsSettings.GetInstance().RegistryPath = "whatever") and to do that I would need a set accessor on RegistryPath (eg. public string RegistryPath { get { return _RegPath; } set { _RegPath = value; } })

     ... is that right?
    LVL 25

    Expert Comment

    You still have one instance, but the point of using singletons is to have one instance, so several "clients" can share the data (or functions, whatever).  Generally (not always) the _value_ of that data is set when the singleton is first created (hence set in the constructor).  Otherwise, you always have to check to see if the value has been set, and if not, either set it or do without.  So the question is, who decides what values the singleton will have?  Can just anyone change the values?  That's why you typically have only get accessors, so you can control who can set the values.

    Like I said, these are _general_ rules, and your application may have a different implementation, but that's how I've typically seen singletons implemented.

    Author Comment

    Got it.  Thanks again for all your help.

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    6 Surprising Benefits of Threat Intelligence

    All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

    Article by: Ivo
    Anonymous Types in C# by Ivo Stoykov Anonymous Types are useful when  we do not need to follow usual work-flow -- creating object of some type, assign some read-only values and then doing something with them. Instead we can encapsulate this read…
    This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
    how to add IIS SMTP to handle application/Scanner relays into office 365.
    Sending a Secure fax is easy with eFax Corporate ( First, Just open a new email message.  In the To field, type your recipient's fax number You can even send a secure international fax — just include t…

    737 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    18 Experts available now in Live!

    Get 1:1 Help Now