43

I definitely remember seeing somewhere an example of doing so using reflection or something. It was something that had to do with SqlParameterCollection which is not creatable by a user (if I'm not mistaken). Unfortunately cannot find it any longer.

Can anyone please share this trick here? Not that I consider it a valid approach in development, I'm just very interested in the possibility of doing this.

stop-cran
  • 4,229
  • 2
  • 30
  • 47
User
  • 30,403
  • 22
  • 79
  • 107

4 Answers4

82

You can use one of the overloads of Activator.CreateInstance to do this: Activator.CreateInstance(Type type, bool nonPublic)

Use true for the nonPublic argument. Because true matches a public or non-public default constructor; and false matches only a public default constructor.

For example:

    class Program
    {
        public static void Main(string[] args)
        {
            Type type=typeof(Foo);
            Foo f=(Foo)Activator.CreateInstance(type,true);
        }       
    }

    class Foo
    {
        private Foo()
        {
        }
    }
Mariano Desanze
  • 7,847
  • 7
  • 46
  • 67
Sean
  • 60,939
  • 11
  • 97
  • 136
  • 1
    In silverlight this matches `CreateInstance(Type type, params object[] args);` which tires to call **public** ctor with **bool** argument. http://msdn.microsoft.com/en-us/library/system.activator.createinstance%28v=vs.95%29.aspx – Agent_L Sep 18 '14 at 12:38
  • 22
    That is ok if you invoke parameterless constructor. If you want to invoke a private constructor with params, try this: `Foo f =(Foo) Activator.CreateInstance(typeof(Foo), BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { "Param1" }, null,null);` – Mohamed ElHamamsy Aug 08 '16 at 13:33
54
// the types of the constructor parameters, in order
// use an empty Type[] array if the constructor takes no parameters
Type[] paramTypes = new Type[] { typeof(string), typeof(int) };

// the values of the constructor parameters, in order
// use an empty object[] array if the constructor takes no parameters
object[] paramValues = new object[] { "test", 42 };

TheTypeYouWantToInstantiate instance =
    Construct<TheTypeYouWantToInstantiate>(paramTypes, paramValues);

// ...

public static T Construct<T>(Type[] paramTypes, object[] paramValues)
{
    Type t = typeof(T);

    ConstructorInfo ci = t.GetConstructor(
        BindingFlags.Instance | BindingFlags.NonPublic,
        null, paramTypes, null);

    return (T)ci.Invoke(paramValues);
}
LukeH
  • 263,068
  • 57
  • 365
  • 409
  • A slight improvement to this handy static method is to build up the parameter types array dynamically – nrjohnstone Nov 09 '14 at 19:46
  • 2
    @nrjohnstone If you mean GetType on each array element it's not possible in general case because of nulls. Also if you try to infer the types in this case you will end up implementing a complete overload resolution according to the language of choice, which is not trivial in case of C#. – George Polevoy Oct 14 '15 at 08:00
1

It will also help if your Type is private or internal:

 public static object CreatePrivateClassInstance(string typeName, object[] parameters)
    {
        Type type = AppDomain.CurrentDomain.GetAssemblies().
                 SelectMany(assembly => assembly.GetTypes()).FirstOrDefault(t => t.Name == typeName);
        return type.GetConstructors()[0].Invoke(parameters);
    }
Mr.B
  • 3,484
  • 2
  • 26
  • 40
1

If the class isn't one of yours, then it sounds like the API was deliberately written to prevent this, which means that it's possible your approach isn't what the API writers intended. Take a look at the docs and see if there's a recommended approach to using this class.

If you do have control over the class and want to implement this pattern, then it's typically implemented via a static method on a class. This is a key concept that makes up the Singleton pattern, too.

For example:

public PrivateCtorClass
{
    private PrivateCtorClass()
    {
    }

    public static PrivateCtorClass Create()
    {
        return new PrivateCtorClass();
    }
}

public SomeOtherClass
{
    public void SomeMethod()
    {
        var privateCtorClass = PrivateCtorClass.Create();
    }
}

The SqlCommandParameter stuff is a good example. They expect you to create parameters by calling things like this:

var command = IDbConnnection.CreateCommand(...);
command.Parameters.Add(command.CreateParameter(...));

My example isn't great code because it doesn't demonstrate setting command parameter properties or reuse of parameters/commands, but you get the idea.

Neil Barnwell
  • 41,080
  • 29
  • 148
  • 220
  • I actually meant if the author if the class (not me) made all constructors private or internal and I cannot modify the class, but really, really want to create an instance of it, then how can I get around this protection and create an instance? – User Apr 02 '09 at 09:29
  • Ahh I see what you mean. Well, it sounds like the API was deliberately written to prevent this, which means that it's possible your approach isn't what the API writers intended. Take a look at the docs and see if there's a recommended approach to using this class. – Neil Barnwell Apr 02 '09 at 10:30