Activator.CreateInstance с закрытым закрытым классом - PullRequest
12 голосов
/ 13 января 2009

Я пытаюсь создать экземпляр 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. New'ing - закрытый класс с внутренним ctor-портом, поддерживаемый с другой перегрузкой CreateInstance или как?

Ответы [ 4 ]

20 голосов
/ 13 января 2009

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

18 голосов
/ 13 января 2009

Я получил это работать так:

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. Пойди разберись.

10 голосов
/ 18 августа 2009

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

0 голосов
/ 21 марта 2017

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