Share via


Instantiating types with no public constructors

It turns out, Activator.CreateInstance and Activator.CreateInstance<T> fail if there is no public parameterless constructor defined on a type we’re trying to instantiate. Even if the constructor is internal (basically, anything other than public), CreateInstance will fail. This one was a surprise actually, I would expect the reflection binder to work for internal constructors at least.

Update: it turns out, there is an overload of Activator.CreateInstance(Type, bool) that does exactly what I want. Don’t use what I posted below :) Thanks to Andrey Shchekin for the tip!

Nevertheless, a more powerful alternative to Activator.CreateInstance in this case is to find the non-public constructor and invoke it manually:

 using System;
using System.Reflection;

class Test
{
    private Test() { }
}

class Program
{
    static void Main(string[] args)
    {
        var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
        var ctor = typeof(Test).GetConstructor(flags, null, new Type[0], null);
        var instance = ctor.Invoke(null);

        //var instance = Activator.CreateInstance<Test>(); // Exception: No parameterless constructor defined for this object.
        //var instance = Activator.CreateInstance(typeof(Test)); // Exception: No parameterless constructor defined for this object.
    }
}

Why do I need this? Well, there is a class in our codebase that everyone was instantiating all over the place. But this class should have inherently been a singleton. I changed the code all over the place to use a singleton instead of instantiating it and I wanted to prohibit people to instantiate this class in the future.

We have a little Singleton helper that essentially looks like this:

 public class Singleton<T> where T : class
{
    static T instance;
    public static T Instance
    { 
        get
        {
            if (instance == null)
            {
                instance = Instantiate();
            }
            return instance;
        }
    }

    static T Instantiate()
    {
        return Activator.CreateInstance<T>();
    }
}

So I would just inherit the class that everyone was using from Singleton like this: CommonClass : Singleton<CommonClass> and make the constructor private so that people can’t instantiate it manually anymore. However this became a problem because the Singleton’s Instantiate() method failed for non-public constructors. Now that I’ve used the approach above, it works fine. Singleton can instantiate the class, but no one else can.

 

P.S. Yes, I know about the right way to implement a singleton, I know about double-check locking and threading and that reflection is bad. But this solves the problem.

P.P.S. Yes, I know about burning the base class and that mixing in a singleton via inheritance is generally a bad idea. It works for us and does it’s job.

P.P.P.S. It occurred to me that if we had extension properties, one could have just made Instance an extension property on every type (that implements a certain “marker” interface). But there is no way currently to mix-in state into existing types (if you don’t look at WPF and their attached properties and dependency properties).