Wednesday, March 23, 2011

Activator.CreateInstance with private sealed class

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?

From stackoverflow
  • 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.

    Robert C. Barth : The docs say CreateInstance only calls public constructors before 2.0sp1. After that, there's a bunch of permissions that are necessary.
  • 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.

  • 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.

  • 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

0 comments:

Post a Comment