Example #1
0
        /// <summary>
        /// Creates a new Singleton.
        /// </summary>
        /// <param name="getInstanceFunction">A function to create an instance of the given type. If null will be set to default constructor of this type.</param>
        /// <param name="initializeDirectly">Shall the Singleton be directly initialized upfront?</param>
        /// <exception cref="MissingMethodException">Throws a MissingMethodException when no getInstanceFunction is given and the type does not contain a default constructor and is no ValueType.</exception>
        public Singleton(Func <T> getInstanceFunction = null, bool initializeDirectly = false)
        {
            _instance    = default(T);
            _getInstance = getInstanceFunction;

            if (_getInstance == null)
            {
                var ctor = typeof(T).GetConstructor(Type.EmptyTypes);

                if (ctor == null)
                {
                    if (typeof(T).IsValueType)
                    {
                        _initialized = true; // has already been initialized in the first line to default(T).
                        return;
                    }
                    else
                    {
                        throw new MissingMethodException("There is no empty constructor defined for this type. Please implement an empty constructor or provide a initialization function.");
                    }
                }
                else // just for code clarity.
                {
                    // Create method to call the empty constructor for the given type.
                    // See https://stackoverflow.com/questions/10593630/create-delegate-from-constructor

                    DynamicMethod dynamic = new DynamicMethod(string.Empty, typeof(T), Type.EmptyTypes, typeof(T));
                    ILGenerator   il      = dynamic.GetILGenerator();

                    il.DeclareLocal(typeof(T));
                    il.Emit(OpCodes.Newobj, ctor);
                    il.Emit(OpCodes.Stloc_0);
                    il.Emit(OpCodes.Ldloc_0);
                    il.Emit(OpCodes.Ret);

                    _getInstance = (Func <T>)dynamic.CreateDelegate(typeof(Func <T>));
                }
            }

            if (initializeDirectly)
            {
                if (!_initialized)
                {
                    _instance = _getInstance();
                }

                _initialized = true;
            }
            else
            {
                _singletonLock = new UsableMutexSlim();
            }
        }