none
Generic singleton instance generator RRS feed

  • Question

  • Hi,

    I am looking for a class which can return singleton instance of the type that client specifies. I want to use "Lazy" keyword feature so that I don't need to make the method thread-safe.

    Current working solution I have is below but I need to take care of thread safe here :(

    public class InstanceGenerator
        {
            static Dictionary<string, object> typeDict = new Dictionary<string, object>();
            static readonly object lockObj = new object();
            public static object GetInstance(string type)
            {
                lock (lockObj)
                {
                    if (!typeDict.ContainsKey(type))
                        typeDict.Add(type, Activator.CreateInstance(Type.GetType(type)));
                }
                return typeDict[type];
            }
        }
    
    
    // Client
    
    var obj = InstanceGenerator.GetInstance("GenericSingleton.Sample");

    While I am looking for something like below but I want to pass type value as string from client-

    public abstract class SingletonBase<T> where T : class
        {
            private static readonly Lazy<T> sInstance = new Lazy<T>(
                () => CreateInstanceOfT());
            public static T Instance(string typeName)
            {
                return sInstance.Value;
            }
            private static T CreateInstanceOfT()
            {
                return Activator.CreateInstance(typeof(T), true) as T;
            }
        }

    Tuesday, November 11, 2014 3:00 PM

Answers

  • "inbuilt way of thread safing"? There is no such thing. You must use some kind of lock to make an insert operation like the one you are doing thread-safe.

    Please also remember to mark helpful posts as answer and/or helpful.

    Wednesday, November 12, 2014 9:45 PM

All replies

  • Your GetInstance method in your InstanceGenerator class looks pretty thread-safe since you are locking around the insertion to the dictionary.

    I am not sure if I understand your issue here but if you want to store objects of type Lazy<T> rather than types of T in your dictionary, you could use the MakeGenericType method something like this:

      public class InstanceGenerator
      {
        static Dictionary<string, object> typeDict = new Dictionary<string, object>();
        
        static readonly object lockObj = new object();
    
        public static object GetInstance(string type) {
    
          Type t = Type.GetType(type);
          Type lazy = typeof(Lazy<>);
          Type lazyt = lazy.MakeGenericType(t); //= Lazy<T> type
    
          object instance = Activator.CreateInstance(lazyt); //instance of Lazy<T>
    
          lock (lockObj) {
            if (!typeDict.ContainsKey(type))
              typeDict.Add(type, instance);
          }
          return typeDict[type];
        }
      }
    

    Please refer to my blog post for more information about generic type parameters and dynamic types in C#: http://blog.magnusmontin.net/2014/10/31/generic-type-parameters-and-dynamic-types-in-csharp/

    Please also remember to mark helpful posts as answer and/or helpful.

    Tuesday, November 11, 2014 4:01 PM
  • What I meant was I don't want to use lock for making it threadsafe rather any inbuilt way of thread safing
    Wednesday, November 12, 2014 5:39 PM
  • "inbuilt way of thread safing"? There is no such thing. You must use some kind of lock to make an insert operation like the one you are doing thread-safe.

    Please also remember to mark helpful posts as answer and/or helpful.

    Wednesday, November 12, 2014 9:45 PM
  • I mean I don't want to make it thread safe from my code rather use any existing .Net feature/class/structure to achieve the same.
    Friday, November 21, 2014 6:59 AM
  • Then you have completely misunderstood the use of the thread-safe collections that were introduced in .NET 4. Although they allow multi-threaded add and remove operations, you still need to lock around the check (ContainsKey) and the insertion (Add) like this:

    if (!typeDict.ContainsKey(type))
              typeDict.Add(type, instance);

    Just because a collection is thread-safe does not mean that this code is:

    //this code is not thread-safe !!!:
    
    if(!threadSafeCollection.Contains(type))
     threadSafeCollection.Add(instance);
    

    But please don't ask several questions in the same thread and please close your threads by marking helpful posts as answer.
    Friday, November 21, 2014 9:52 AM