Search code examples
c#design-patternsparameterssingletonarguments

Singleton with parameters


I need a singleton class to be instantiated with some arguments. The way I'm doing it now is:

class SingletonExample
{
     private SingletonExample mInstance;
     //other members... 
     private SingletonExample()
     {

     } 
     public SingletonExample Instance
     {
         get
         {
              if (mInstance == null)
              {
                  throw new Exception("Object not created");
              }
              return mInstance;
         }
     }

     public void Create(string arg1, string arg2)
     {
         mInstance = new SingletonExample();
         mInstance.Arg1 = arg1;
         mInstance.ObjectCaller = new ObjectCaller(arg2);
         //etc... basically, create object...
     } 
}

The instance is created 'late', meaning I don't have all of the needed arguments on app startup.

In general I don't like forcing an ordering of method calls, but I don't see another way here. The IoC wouldn't resolve it either, since where I can register it in the container, I can also call Create()...

Do you consider this an OK scenario? Do you have some other idea?

edit: I know that what I wrote as an example it's not thread safe, thread-safe isn't part of the question


Solution

  • A Singleton with parameters smells fishy to me.

    Consider whateva's answer and the following code:

    Singleton x = Singleton.getInstance("hello", "world");
    Singleton y = Singleton.getInstance("foo", "bar");
    

    Obviously, x==y and y works with x's creation parameters, while y's creation parameters are simply ignored. Results are probably... confusing at least.

    If you really, really fell like you have to do it, do it like this:

    class SingletonExample
    {
         private static SingletonExample mInstance;
         //other members... 
         private SingletonExample()
         {  // never used
            throw new Exception("WTF, who called this constructor?!?");
         }
         private SingletonExample(string arg1, string arg2)
         {
             mInstance.Arg1 = arg1;
             mInstance.ObjectCaller = new ObjectCaller(arg2);
             //etc... basically, create object...    
         } 
         public static SingletonExample Instance
         {
             get
             {
                  if (mInstance == null)
                  {
                      throw new Exception("Object not created");
                  }
                  return mInstance;
             }
         }
    
         public static void Create(string arg1, string arg2)
         {
             if (mInstance != null)
             {
                 throw new Exception("Object already created");
             }
             mInstance = new SingletonExample(arg1, arg2);             
         } 
    }
    

    In a multithreading environment, add synchronisation to avoid race conditions.