2010-11-02 9 views
38

J'ai quelque chose le long des lignes de ce:instanciation d'un constructeur avec des paramètres dans une classe interne avec la réflexion

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

et

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

    # region Constructors 

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

    internal xxx() 
    { 
    } 

    ... 
} 

Et je reçois:

jeté exception: Système .MissingMethodException: Constructeur sur le type 'xxxx.xxx' non trouvé ..

Des idées?

+0

Je pensais que vous vouliez que 'parameter' soit la chose que vous avez passée comme' x'. Cependant, je viens de réaliser que ce n'est probablement pas ce que vous vouliez dire et, en regardant les autres réponses, il semble que je ne sois pas seul. Si c'est correct, je suggère de renommer 'parameter' en' parameters'. Ou mieux encore, se passer totalement de 'parameter':' Activator.CreateInstance (typeToInstantiate, nouvel objet [] {x}) '. –

Répondre

75

Le problème est que Activator.CreateInstance(Type, object[]) ne considère pas les constructeurs non publiques.

Exceptions

MissingMethodException: Aucun constructeur public n'a été trouvé.

Ceci est facilement montré en changeant le constructeur à public visibilité; le code fonctionne alors correctement.

est ici une solution de contournement (testé):

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 vous avez besoin que le constructeur parameterless ceci fonctionne ainsi:

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

la plupart de toutes vos réponses étaient valides, merci. – KP65

+0

Je devrais ajouter ceci. –

+10

J'ai testé cela et je pense qu'il vaut la peine de mentionner que cette méthode fonctionne UNIQUEMENT avec les constructeurs non-publics. Pour le faire fonctionner avec les constructeurs public et non public, modifiez 'BindingFlags' en' BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance' – ken

1

changement à

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

Ceci est parce que votre constructeur attend également un tableau d'objets et activateur divise déjà en place en objets distincts

3

Vous devez appeler a different overload of Activator.CreateInstance qui vous permet de passer un nonPublic ou BindingFlags paramètre.Je trouve toutes ces surcharges CreateInstance maladroites; ce que je préfère faire est:

  1. Appel typeToInstantiate.GetConstructor(), en passant BindingFlags.NonPublic
  2. Appel ConstructorInfo.Invoke, passant le paramètre du constructeur
18

(testé avec succès)

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

Il y a deux questions ces adresses:

  • le new object[] {parameter} aide il gérer la question de passer un object[] comme un seul paramètrede méthode qui prend un argument params object[]
  • le BindingFlags aide à résoudre le constructeur non publiques

(les deux null s se rapportent au liant ; le comportement par défaut du classeur est correct pour ce que nous voulons)