Kini
Kini

Reputation: 23

Using a Singleton in C# App

I have spent last couple of days reading about and trying different methods for creating and using a singleton instance of one of my class files and then using the reference as I need throughout the life of the program here on stackoverflow and well as a few other sites, and have found that there are soooo many opinions, suggestions and examples that work that I have gotten a little confused, especially when it comes to actually using the singleton object.

I have something that functions but I do not believe it is the most correct way and that I may be missing a step.

I have a simple class file in my program called clsRegistry implemented as a singleton.

public sealed class clsRegistry
{
  //http://tech.pro/tutorial/625/csharp-tutorial-singleton-pattern

  private static clsRegistry RegInstance;

  private clsRegistry() { }

  public static clsRegistry GetInstance()
  {
    lock (typeof(clsRegistry))
    {
      if (RegInstance == null)
      {
        RegInstance = new clsRegistry();
      }
      return RegInstance;
    }
  }

  public string dataBase { get; set; }
  public string userId { get; set; }
  public string passWord { get; set; }

  public void ReadKeys()
  {
    //http://stackoverflow.com/questions/1388787/information-in-registry
    RegistryKey key = Registry.LocalMachine.OpenSubKey(@"Software\Key1\Key2\Key3");
    dataBase = key.GetValue("ADODataSource").ToString().Trim();
    userId = key.GetValue("ServerUserID").ToString().Trim();
    passWord = key.GetValue("ServerPassword").ToString().Trim();
  }
}   // end class definition

Which when called from the Main method implements correctly and calls the one public method (ReadKeys) in the class

static class Program
{
  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  [STAThread]
  static void Main()
  {
    // create instance of registry class 
    clsRegistry regData = clsRegistry.GetInstance();

    // call method
    regData.ReadKeys();

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    //Application.Run(new frmMain());
    Application.Run(new frmLogin());
  }
}

After the singleton of the class is created I have a small login form loading and I want the database name from the singleton to display in the form and this is where I have less than elegant code.

private void frmLogin_Load(object sender, EventArgs e)
{
  // create a 'new' instance to the singleton?
  clsRegistry regData = clsRegistry.GetInstance();

  lblDataBase.Text = regData.dataBase;
}

Do I really need to create another reference to my singleton object in order to read some values (or later on call another method) or am I missing a step some where? I am operating under the assumption that once I create an instance of a class as a singleton and it remains within the same namespace I can access any public value or method. No?

For reference I am using Visual Studio 2010 and the 4.0 framework (and yes I am another classic VB developer thats FINALLY jumping ship)

Upvotes: 2

Views: 641

Answers (3)

Dennis Traub
Dennis Traub

Reputation: 51634

First of all: In C# you don't need locks etc for this. Just create the instance through static initialization and you're threadsafe and good to go.

public sealed class ClsRegistry
{
    private static ClsRegistry RegInstance = new ClsRegistry();

    private clsRegistry() { }

    public static ClsRegistry Instance {
        get { return RegInstance; }
    }

    public string DataBase { get; set; }
    public string UserId { get; set; }
    public string PassWord { get; set; }

    public void ReadKeys()
    {
        // ...
    }
}

Having that said you can then simply access the singleton and its properties/methods through ClsRegistry.Instance without the need to assign it to a new variable first:

static void Main()
{
    ClsRegistry.Instance.ReadKeys();
    // ...
}

and

private void frmLogin_Load(object sender, EventArgs e)
{
    lblDataBase.Text = ClsRegistry.Instance.DataBase;
}

Please note that I changed the names of your class and properties so that each first letter is a capital, which is kind of a convention in C#

Upvotes: 1

Alan
Alan

Reputation: 7951

First of all, Microsoft has guidelines for implementing a singleton specifically in C# that explains in great detail the best way to create a single and multi-threaded singleton class.

As far as your code:

  1. You are not creating another instance of your object when you call GetInstance. The code returns the previously created instance. It only instantiates a new instance of the class if it is null (just once).

  2. You should make Instance a property instead of a method in .NET (it's just cleaner).

  3. You should stick to Pascal case when writing .NET code, if you were writing Java code, I'd suggest you stick to camelCase because that is the standard casing for the language.

Upvotes: 2

Servy
Servy

Reputation: 203819

You need to ask the singleton for its reference to access the values, yes. You don't need to store that reference in a local variable if you don't want to, although you certainly can. If you don't want to you can access the value from the instance directly:

lblDataBase.Text = clsRegistry.GetInstance().dataBase;

Upvotes: 1

Related Questions