views:

186

answers:

4

I want to write a generic singleton with an external constructor. In other words the constructor can be modified. I have 2 designs in my mind but I don't know whether they are practical or not.

  • First one is to enforce derived class' constructor to be non-public but I do not know if there is a way of it?

  • Second one is to use a delegate and call it inside the constructor?

It isn't necessarily to be a constructor. The reason I chose custom constructor is doing some custom initializations.

Any suggestions would be appreciated :)

+2  A: 

That doesn't sound nice. I wonder if configuring this through IoC is going to be simpler and easier to support. Most IoC containers will support singeton-style object re-use, and highly configurable initialization. Without the side-effect making your object all ugly.

Singleton is nice, but is vastly over-used. Of course I'm as guilty of this as the next geek...

Marc Gravell
I am not very familiar with IoC. Can you give an example?
Heka
@Heka - look at the "logger" example here: http://www.pnpguidance.net/News/StructureMapTutorialDependencyInjectionIoCNET.aspx
Marc Gravell
Singletons are like fast food; quick and convenient, but decidedly unhealthy in the long run.
Dan Bryant
+1  A: 

Here's one way to do this, If at all I could get you right.

public abstract class MySingletonBase<T>
    where T : class
{
    protected MySingletonBase()
    {
    }

    // All other functions that will be inherited.
}

public class MySingleton<T> : MySingletonBase<T>
    where T : class
{
    private static MySingleton<T> instance;
    protected MySingleton()
    {
    }

    public static MySingleton<T> GetInstance()
    {
        if (instance == null)
        {
            instance = new MySingleton<T>();
        }
        return instance;
    }
}
this. __curious_geek
Yes it is a good solution but I prefer something simpler to use. And I think I have found something :) Let me post the code.
Heka
A: 

Ok here is my solution. I used reflection to check for public constructors. Please comment if I'm missing something.

      public abstract class Singleton<T> where T: class
      {

        private static volatile T _instance;

        private static object _lock = new object();

        protected Singleton()
        {
          ConstructorInfo[] constructorPublic = typeof(T).GetConstructors(BindingFlags.Public | BindingFlags.Instance);
          if (constructorPublic.Length > 0)
          {
            throw new Exception(String.Format("{0} has one or more public constructors so the property cannot be enforced.",
                                              typeof(T).FullName));
          }
        }

        public static T Instance
        {
          get
          {
            if (_instance == null)
            {
              lock (_lock)
              {
                if (_instance == null)
                {
                  ConstructorInfo constructorNonPublic = null;

                  try
                  {
                    constructorNonPublic = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null,
                                                            new Type[0], null);
                  }
                  catch (Exception e)
                  {
                    throw e;
                  }

                  if (constructorNonPublic == null || constructorNonPublic.IsAssembly)
                  {
                    throw new Exception(String.Format("A private or protected constructor is missing for {0}",
                                                      typeof (T).Name));
                  }

                  _instance = constructorNonPublic.Invoke(null) as T;
                }
              }
            }

            return _instance;
          }
        }
      }
Heka
A: 

You can try to use factory pattern to create a singleton factory, which will produce the concrete singletons.

sza