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

Создание экземпляра конструктора с параметрами во внутреннем классе с отражением

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

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" не найден..

Любые идеи?

4b9b3361

Ответ 1

Проблема заключается в том, что 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)

Ответ 2

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

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 относятся к связующему, поведение связующего по умолчанию отлично подходит для того, что мы хотим)

Ответ 3

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

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

  • Вызов typeToInstantiate.GetConstructor(), передача BindingFlags.NonPublic
  • Вызвать ConstructorInfo.Invoke, передав ему параметр конструктора

Ответ 4

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

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

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