c# - Activator.CreateInstance con clase privada sellada
reflection ado.net (4)
Mi primer pensamiento sería obtener ConstructorInfo
usando ConstructorInfo constructorInfo = Type.GetConstructor()
y luego constructorInfo.Invoke()
eso. Sospecho que Activator.CreateInstance
hace que sea difícil llamar a constructores a los que normalmente no tendrías acceso, aunque no recuerdo haberlo intentado.
Estoy intentando actualizar una instancia de LocalCommand que es una clase privada de System.Data.SqlClient.SqlCommandSet. Parece que soy capaz de tomar la información del tipo muy bien:
Assembly sysData = Assembly.Load("System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
localCmdType = sysData.GetType("System.Data.SqlClient.SqlCommandSet+LocalCommand");
pero Activator.CreateInstance arroja una excepción cuando intento instanciarlo:
object item = Activator.CreateInstance(localCmdType,
new object[] { commandText, parameters, num7, commandType });
System.MissingMethodException: No se encontró Constructor en el tipo ''System.Data.SqlClient.SqlCommandSet + LocalCommand''.
Los argumentos del constructor coinciden con la firma que veo en Reflector. ¿Es nueva una clase privada con un ctor interno compatible con una sobrecarga CreateInstance diferente o qué?
Lo tengo para trabajar de esta manera:
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" });
}
}
El truco fue ir tras el constructor específicamente con GetConstructor
lugar de tratar de encontrarlo en los resultados de GetConstructors
. Imagínate.
Es posible que llegue un poco tarde para responder, pero me encontré con un problema similar que encaja en este tema. Quería crear una instancia de un constructor no público utilizando Activator.CreateInstance y pasarle argumentos.
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;
}
La parte difícil fue las banderas vinculantes. Mi primer instinto fue usar BindingFlags.CreateInstance | BindingFlags.NonPublic, sin embargo, provocó una excepción: No se encontró el constructor MissingMethodException en el tipo ''Node''. Disfrutar
El truco es asegurarse de usar la sobrecarga CreateInstance
correcta:
// WRONG
... Activator.CreateInstance(
type,
BindingFlags.Instance
| BindingFlags.NonPublic
);
Esto llama a la sobrecarga de params
, que se configurará por defecto en Instance | Public | CreateInstance
Instance | Public | CreateInstance
Instance | Public | CreateInstance
, y sus banderas de enlace se pasarán como argumentos al constructor, dando la vaga MissingMethodException
.
Además, use Instance | Public | NonPublic
Instance | Public | NonPublic
Instance | Public | NonPublic
si no está seguro de la visibilidad del constructor:
// right
... Activator.CreateInstance(
type,
BindingFlags.Instance
| BindingFlags.Public
| BindingFlags.NonPublic,
null,
new object[] { }, // or your actual constructor arguments
null
);