tags:

views:

218

answers:

3

I ran into a problem today and a friend recommended I use a global static instance or more elegantly a singleton pattern. I spent a few hours reading about singletons but a few things still escape me.

Background: What Im trying to accomplish is creating an instance of an API and use this one instance in all my classes (as opposed to making a new connection, etc).

There seems to be about 100 ways of creating a singleton but with some help from yoda I found some thread safe examples. ..so given the following code:

public sealed class Singleton
{
     public static Singleton Instance { get; private set; }

     private Singleton()
     {
        APIClass api = new APIClass();  //Can this be done?
     }

     static Singleton() { Instance = new Singleton(); }
}

How/Where would you instantiate the this new class and how should it be called from a separate class?

EDIT: I realize the Singleton class can be called with something like

Singleton obj1 = Singleton.Instance();

but would I be able to access the methods within the APIs Class (ie. obj1.Start)? (not that I need to, just asking)

EDIT #2: I might have been a bit premature in checking the answer but I do have one small thing that is still causing me problems. The API is launching just fine, unfortunately Im able to launch two instances?

New Code

public sealed class SingletonAPI
{
 public static SingletonAPI Instance { get; private set; }

 private SingletonAPI() {}

 static SingletonAPI() { Instance = new SingletonAPI(); }     

 // API method:
 public void Start() { API myAPI = new API();}
 }

but if I try to do something like this...

SingletonAPI api = SingletonAPI.Instance;
api.Start();
SingletonAPI api2 = SingletonAPI.Instance;  // This was just for testing.
api2.Start();

I get an error saying that I cannot start more than one instance.

+1  A: 

You wouldn't instantiate the class - the pattern you're using basically instantiates itself the first time it's used. The advantage to the method you're using is that it's thread safe (will only instantiate once, no matter how many threads try to access it), lazy (it won't instantiate until you try to access the Singleton class), and simple in implementation.

All you need to do to use this is to do:

 Singleton.Instance.MyMethodOnSingleton();

Or, alternatively:

 Singleton myInstance = Singleton.Instance; // Will always be the same instance...
 myInstance.DoSomething();
Reed Copsey
also i would recomend Farstucker read about singletons on msdn http://msdn.microsoft.com/en-us/library/ms998558.aspx
vittore
Believe it or not, I did read that. I guess Im just confused on how to instantiate a completely different class and use it globally. I added some code to help explain what Im trying to do.
Farstucker
+3  A: 

Here is the official Microsoft approach.

The beauty of the singleton is that you can use and access it anywhere in your code without having to create an instance of the class. In fact that is it's raison d'etre, a single instance of a class eg

Singleton.Instance.MyValue and Singleton.Instance.DoSomething();

James Westgate
+2  A: 

Why not just add a public APIClass property to your singleton?

public sealed class Singleton
{
     public static Singleton Instance { get; private set; }

     private APIClass _APIClass; 

     private Singleton()
     {
        _APIClass = new APIClass();  
     }

     public APIClass API { get { return _APIClass; } }

     static Singleton() { Instance = new Singleton(); }     
}

Then your calling site looks like:

Singleton.Instance.API.DoSomething();

Or if you are the author of the API class, you could make it a singleton itself, instead of wrapping it in a singleton:

public sealed class SingletonAPI
{
     public static SingletonAPI Instance { get; private set; }

     private SingletonAPI() {}

     static SingletonAPI() { Instance = new SingletonAPI(); }     

     // API method:
     public void DoSomething() { Console.WriteLine("hi"); }
}

API call:

SingletonAPI.Instance.DoSomething();
Charles
@charles Thank you very much, thats exactly what I needed.
Farstucker