Подтвердить что ты не робот

Activator.CreateInstance с закрытым закрытым классом

Я пытаюсь создать экземпляр 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");

но Activator.CreateInstance генерирует исключение, когда я пытаюсь его создать:

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

System.MissingMethodException: конструктор по типу 'System.Data.SqlClient.SqlCommandSet + LocalCommand' не найден.

Аргументы конструктора соответствуют сигнатуре, которую я вижу в Reflector. Является ли новый класс закрытым классом с внутренним ctor, поддерживаемым другой перегрузкой CreateInstance или что?

4b9b3361

Ответ 1

Моя первая мысль заключалась в том, чтобы получить ConstructorInfo с помощью ConstructorInfo constructorInfo = Type.GetConstructor(), а затем constructorInfo.Invoke(). Я подозреваю, что Activator.CreateInstance затрудняет вызов конструкторов, к которым у вас обычно нет доступа, хотя я не помню, как это пробовал сам.

Ответ 2

У меня это получилось так:

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" });
    }
}

Хитрость заключалась в том, чтобы после конструктора пойти непосредственно с GetConstructor, а затем попытаться найти его в результатах GetConstructors. Наведите указатель мыши.

Ответ 3

Возможно, мне немного поздно ответить, но я столкнулся с аналогичной проблемой, которая вписывается в эту тему. Я хотел создать экземпляр не публичного конструктора с помощью 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;
        }

Трудная часть была обязательными флагами. Мой первый инстинкт заключался в использовании BindingFlags.CreateInstance | BindingFlags.NonPublic, однако, вызвало исключение: MissingMethodException Конструктор по типу 'Node' не найден. Наслаждайтесь

Ответ 4

Трюк должен убедиться в правильной перегрузке CreateInstance:

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

Это вызывает перегрузку params, которая по умолчанию будет Instance | Public | CreateInstance, а ваши флаги привязки будут переданы в качестве аргументов конструктору, что даст неопределенный MissingMethodException.

Кроме того, используйте Instance | Public | NonPublic, если вы не уверены в видимости конструктора:

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