Создание конструктора с параметрами во внутреннем классе с отражением - PullRequest
49 голосов
/ 02 ноября 2010

У меня есть что-то вроде этого:

object[] parameter = new object[1];
parameter[0] = x;
object instantiatedType =
Activator.CreateInstance(typeToInstantiate, parameter);

и

internal class xxx : ICompare<Type>
{
    private object[] x;

    # region Constructors

    internal xxx(object[] x)
    {
        this.x = x;
    }

    internal xxx()
    {
    }

    ...
}

И я получаю:

сгенерировано исключение: System.MissingMethodException: конструктор типа «xxxx.xxx» не найден ..

Есть идеи?

Ответы [ 4 ]

87 голосов
/ 02 ноября 2010

Проблема в том, что Activator.CreateInstance(Type, object[]) не учитывает непубличные конструкторы.

Исключения

MissingMethodException: нет соответствия публичный конструктор найден.

Это легко показать, изменив конструктор на public видимость; тогда код работает правильно.

Вот один из обходных путей (проверено):

 BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
 CultureInfo culture = null; // use InvariantCulture or other if you prefer
 object instantiatedType =   
   Activator.CreateInstance(typeToInstantiate, flags, null, parameter, culture);

Если вам нужен только конструктор без параметров, это также будет работать:

//using the overload: public static object CreateInstance(Type type, bool nonPublic)
object instantiatedType = Activator.CreateInstance(typeToInstantiate, true)
25 голосов
/ 02 ноября 2010

(успешно протестировано)

object instantiatedType =
   Activator.CreateInstance(typeToInstantiate,
   System.Reflection.BindingFlags.NonPublic |
     System.Reflection.BindingFlags.Instance,
   null, new object[] {parameter}, null);

Есть два вопроса по этому адресу:

  • new object[] {parameter} помогает решить проблему передачи object[] в качестве одного параметра метода, который принимает params object[] аргумент
  • BindingFlags помогает разрешить непубличный конструктор

(два null относятся к связующему ; поведение связующего по умолчанию подходит для того, что мы хотим)

4 голосов
/ 02 ноября 2010

Вам необходимо вызвать другую перегрузку Activator.CreateInstance, которая позволяет передавать параметр nonPublic или BindingFlags.

Я нахожу все эти CreateInstance перегрузки неуклюжими; что я предпочитаю делать так:

  1. Звонок typeToInstantiate.GetConstructor(), прохождение BindingFlags.NonPublic
  2. Вызовите ConstructorInfo.Invoke, передав ему параметр конструктора
1 голос
/ 02 ноября 2010

измените его на

Activator.CreateInstance(typeToInstantiate,new object[] { parameter });

Это потому, что ваш конструктор также ожидает массив объектов и активатор уже разбивает его на отдельные объекты

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...