2010-11-02 10 views
38

tengo algo en la línea de este:Crear instancias de un constructor con parámetros en una clase interna con la reflexión

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

y

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

    # region Constructors 

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

    internal xxx() 
    { 
    } 

    ... 
} 

Y consigo:

arrojó excepción: Sistema .MissingMethodException: Constructor en el tipo 'xxxx.xxx' no encontrado ...

¿Alguna idea?

+0

Originalmente pensé que el 'parámetro' pretendía ser lo que pasó como' x'. Sin embargo, me di cuenta de que probablemente no es lo que querías decir y, mirando las otras respuestas, parece que no estoy solo. Si esto es correcto, sugiero cambiar el nombre de 'parameter' a' parameters'. O mejor aún, prescinda de 'parameter' en total:' Activator.CreateInstance (typeToInstantiate, new object [] {x}) '. –

Respuesta

75

La cuestión es que Activator.CreateInstance(Type, object[]) no tiene en cuenta los constructores no públicas.

excepciones

MissingMethodException: No se encontraron a juego constructor público.

Esto se muestra fácilmente al cambiar el constructor a public visibilidad; el código luego funciona correctamente.

Aquí hay una solución (probado):

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); 

Si sólo necesita el constructor sin parámetros que esto funcionará así:

//using the overload: public static object CreateInstance(Type type, bool nonPublic) 
object instantiatedType = Activator.CreateInstance(typeToInstantiate, true) 
+0

la mayoría de sus respuestas fueron válidas, gracias. – KP65

+0

Debo marcar esto como favorito. –

+10

Probé esto y creo que vale la pena mencionar que este método SÓLO funciona con constructores no públicos. Para que funcione tanto con constructores públicos como no públicos, cambie 'BindingFlags' por' BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance' – ken

1

cambio a

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

Esto es porque su constructor también espera una matriz de objetos y activador ya se divide para arriba en objetos separados

3

Es necesario llamar a different overload of Activator.CreateInstance que permite pasar un nonPublic o BindingFlags parámetro.

Encuentro todas estas CreateInstance sobrecargas torpes; lo que prefiero hacer es:

  1. llamada typeToInstantiate.GetConstructor(), pasando BindingFlags.NonPublic
  2. llamada ConstructorInfo.Invoke, pasándole el parámetro constructor
18

(probado con éxito)

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

Hay dos cuestiones esto direcciones:

  • la new object[] {parameter} ayuda que manejar el tema de pasar una object[] como una sola parámetro del método que toma un argumento params object[]
  • la BindingFlags ayuda a resolver el constructor no pública

(los dos null s se refieren a la carpeta ; el comportamiento del encuadernador predeterminado está bien para lo que queremos)

Cuestiones relacionadas