Создание конструктора с параметрами во внутреннем классе с отражением
У меня есть что-то вроде этого:
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 ответа
Проблема в том, что 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)
(проверено успешно)
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
s относятся к связующему; поведение связующего по умолчанию хорошо для того, что мы хотим)
Вам нужно вызвать другую перегрузкуActivator.CreateInstance
что позволяет вам передать nonPublic
или же BindingFlags
параметр.
Я нахожу все это CreateInstance
перегрузки неуклюжие; что я предпочитаю делать, это:
- Вызов
typeToInstantiate.GetConstructor()
, проходяBindingFlags.NonPublic
- Вызов
ConstructorInfo.Invoke
, передав ему параметр конструктора
Измените это на
Activator.CreateInstance(typeToInstantiate,new object[] { parameter });
Это потому, что ваш конструктор также ожидает массив объектов и активатор уже разбивает его на отдельные объекты