views:

1718

answers:

4

I'm trying to new up a LocalCommand instance which is a private class of System.Data.SqlClient.SqlCommandSet. I seem to be able to grab the type information just fine:

Assembly sysData = Assembly.Load("System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
localCmdType = sysData.GetType("System.Data.SqlClient.SqlCommandSet+LocalCommand");

but Activator.CreateInstance throws an exception when I try to instantiate it:

object item = Activator.CreateInstance(localCmdType,
  new object[] { commandText, parameters, num7, commandType });

System.MissingMethodException: Constructor on type 'System.Data.SqlClient.SqlCommandSet+LocalCommand' not found.

The constructor arguments match the signature I see in Reflector. Is new'ing up a private class with an internal ctor supported with a different CreateInstance overload or what?

+5  A: 

My first thought would be to get the ConstructorInfo using Type.GetConstructor, and Invoke that. I suspect that Activator.CreateInstance makes it hard to call constructors you wouldn't normally have access to, although I don't remember trying it myself.

Jon Skeet
The docs say CreateInstance only calls public constructors before 2.0sp1. After that, there's a bunch of permissions that are necessary.
Robert C. Barth
Good call on GetConstructor(), that does work. I find it strange considering that the GetConstructor call looks very similar to one of the Activator.CreateInstance() overloads.
A: 

I "think" that activator requires a public constructor in order to work and if I am reading what you put correctly, then it won't work.

I've run into this a couple times before and was annoyed that I would have to adjust my class design to get around this when dealing with dynamically creating instances.

Programmin Tool
+5  A: 

I got it to work this way:

using System;
using System.Reflection;

class Test
{
    public String X { get; set; }

    Test(String x)
    {
     this.X = x;
    }
}

class Program
{
    static void Main()
    {
     Type type = typeof(Test);

     ConstructorInfo c = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, 
      null, new Type[] { typeof(String) }, null);

     Object o = c.Invoke(new Object[] { "foo" });
    }
}

The trick was to go after the constructor specifically with GetConstructor rather then trying to find it in the results of GetConstructors. Go figure.

Andrew Hare
Thanks for the example!
+1  A: 

I might be a little late in responding, but I ran into a similar problem that fits into this topic. I wanted to instantiate a non public constructor using Activator.CreateInstance and passing it arguments.

    public class Node
    {
        string name;
        Node parent;
        protected Node(string name,Node parent)
        {
           this.name = name;
           this.parent = parent;
        }
        public static Node Create(string name,Node parent)
        {
           Node result = Activator.CreateInstance(typeof(Node),BindingFlags.Instance  | BindingFlags.NonPublic,null, new object[] { name, parent }, null) as Node;
           return result;
        }

The tricky part was the binding flags. My first instinct was to use BindingFlags.CreateInstance | BindingFlags.NonPublic, however that caused an exception to be thrown: MissingMethodException Constructor on type 'Node' not found. Enjoy