2010-11-02 10 views
38

ho qualcosa sulla falsariga di questo:un'istanza di un costruttore con parametri in una classe interna con la riflessione

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

e

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

    # region Constructors 

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

    internal xxx() 
    { 
    } 

    ... 
} 

E ottengo:

gettato un'eccezione: Sistema .MissingMethodException: costruttore su tipo 'xxxx.xxx' non trovato ..

Qualche idea?

+0

Originariamente pensavo che 'parametro' fosse la cosa che avevi passato come' x'. Tuttavia, ho appena realizzato che probabilmente non è quello che intendevi e, guardando le altre risposte, sembra che non sia il solo. Se questo è corretto, suggerisco di rinominare 'parameter' in' parameters'. O meglio ancora, rinunciare al 'parametro' del tutto:' Activator.CreateInstance (typeToInstantiate, new object [] {x}) '. –

risposta

75

Il problema è che Activator.CreateInstance(Type, object[]) non considera i costruttori non pubblici.

eccezioni

MissingMethodException: No corrispondenza costruttore pubblico è stato trovato.

Questo è facilmente visibile cambiando il costruttore in public visibilità; il codice quindi funziona correttamente.

Ecco uno soluzione (testato):

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

Se si richiede solo il costruttore senza parametri questo funzionerà così:

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

la maggior parte di tutte le tue risposte erano valide, grazie. – KP65

+0

Dovrei aggiungere questo ai segnalibri. –

+10

Ho provato questo e penso che valga la pena ricordare che questo metodo funziona SOLO con costruttori non pubblici. Per farlo funzionare con costruttori pubblici e non pubblici, cambia 'BindingFlags' in' BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance' – ken

1

cambiamento a

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

Questo perché il costruttore si aspetta anche una matrice di oggetti e attivatore divide già in su in oggetti separati

3

È necessario chiamare a different overload of Activator.CreateInstance che consente di passare un nonPublic o BindingFlags parametro.

Trovo tutti questi sovraccarichi CreateInstance maldestri; quello che preferisco fare è:

  1. chiamata typeToInstantiate.GetConstructor(), passando BindingFlags.NonPublic
  2. chiamata ConstructorInfo.Invoke, passandogli il parametro del costruttore
18

(testato con successo)

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

Ci sono due problemi questo indirizzo:

  • il new object[] {parameter} aiuta maneggia la questione del superamento di un object[] come un singolo parametro del metodo che accetta un argomento params object[]
  • il BindingFlags aiuta a risolvere il costruttore non pubblico

(i due null s si riferiscono al legante ; il comportamento predefinito del binder va bene per quello che vogliamo)

Problemi correlati