Activator.CreateInstance与私人密封类

时间:2021-04-16 17:02:41

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:

我正在尝试新建一个LocalCommand实例,它是System.Data.SqlClient.SqlCommandSet的私有类。我似乎能够很好地获取类型信息:

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:

但是当我尝试实例化它时,Activator.CreateInstance会抛出异常:

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

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

System.MissingMethodException:找不到类型为“System.Data.SqlClient.SqlCommandSet + LocalCommand”的构造函数。

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?

构造函数参数匹配我在Reflector中看到的签名。是新的私有类,内部ctor支持不同的CreateInstance重载或什么?

4 个解决方案

#1


My first thought would be to get the ConstructorInfo using ConstructorInfo constructorInfo = Type.GetConstructor(), and then constructorInfo.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.

我的第一个想法是使用ConstructorInfo constructorInfo = Type.GetConstructor()获取ConstructorInfo,然后使用constructorInfo.Invoke()。我怀疑Activator.CreateInstance很难调用你通常无法访问的构造函数,尽管我不记得自己尝试了。

#2


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.

诀窍是专门使用GetConstructor来修改构造函数,而不是试图在GetConstructors的结果中找到它。去搞清楚。

#3


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.

我可能在回复方面有点迟,但我遇到了一个类似的问题,适合这个主题。我想使用Activator.CreateInstance实例化一个非公共构造函数并传递它的参数。

    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

棘手的部分是绑定标志。我的第一直觉是使用BindingFlags.CreateInstance | BindingFlags.NonPublic,但是会引发异常:MissingMethodException找不到类型为“Node”的构造函数。请享用

#4


Trick is to make sure to use the right CreateInstance overload:

诀窍是确保使用正确的CreateInstance重载:

// WRONG
... Activator.CreateInstance(
       type,
       BindingFlags.Instance
       | BindingFlags.NonPublic
    );

This calls the params overload, which will default to Instance | Public | CreateInstance, and your binding flags will be passed as arguments to the constructor, giving the vague MissingMethodException.

这会调用params重载,默认为Instance |公开| CreateInstance,你的绑定标志将作为参数传递给构造函数,给出模糊的MissingMethodException。

Also, use Instance | Public | NonPublic if you aren't sure of the visibility of the constructor:

另外,使用Instance |公开| NonPublic如果您不确定构造函数的可见性:

// right
... Activator.CreateInstance(
       type,
       BindingFlags.Instance
       | BindingFlags.Public
       | BindingFlags.NonPublic,
       null,
       new object[] { }, // or your actual constructor arguments
       null
    );

#1


My first thought would be to get the ConstructorInfo using ConstructorInfo constructorInfo = Type.GetConstructor(), and then constructorInfo.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.

我的第一个想法是使用ConstructorInfo constructorInfo = Type.GetConstructor()获取ConstructorInfo,然后使用constructorInfo.Invoke()。我怀疑Activator.CreateInstance很难调用你通常无法访问的构造函数,尽管我不记得自己尝试了。

#2


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.

诀窍是专门使用GetConstructor来修改构造函数,而不是试图在GetConstructors的结果中找到它。去搞清楚。

#3


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.

我可能在回复方面有点迟,但我遇到了一个类似的问题,适合这个主题。我想使用Activator.CreateInstance实例化一个非公共构造函数并传递它的参数。

    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

棘手的部分是绑定标志。我的第一直觉是使用BindingFlags.CreateInstance | BindingFlags.NonPublic,但是会引发异常:MissingMethodException找不到类型为“Node”的构造函数。请享用

#4


Trick is to make sure to use the right CreateInstance overload:

诀窍是确保使用正确的CreateInstance重载:

// WRONG
... Activator.CreateInstance(
       type,
       BindingFlags.Instance
       | BindingFlags.NonPublic
    );

This calls the params overload, which will default to Instance | Public | CreateInstance, and your binding flags will be passed as arguments to the constructor, giving the vague MissingMethodException.

这会调用params重载,默认为Instance |公开| CreateInstance,你的绑定标志将作为参数传递给构造函数,给出模糊的MissingMethodException。

Also, use Instance | Public | NonPublic if you aren't sure of the visibility of the constructor:

另外,使用Instance |公开| NonPublic如果您不确定构造函数的可见性:

// right
... Activator.CreateInstance(
       type,
       BindingFlags.Instance
       | BindingFlags.Public
       | BindingFlags.NonPublic,
       null,
       new object[] { }, // or your actual constructor arguments
       null
    );