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 или что?
Ответы
Ответ 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
);