2009-01-13 6 views
11

Ich versuche, eine LocalCommand-Instanz neu zu erstellen, die eine private Klasse von System.Data.SqlClient.SqlCommandSet ist. Ich scheine die Typinformationen zu greifen nur gut in der Lage sein:Activator.CreateInstance mit privaten versiegelten Klasse

Assembly sysData = Assembly.Load("System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); 
localCmdType = sysData.GetType("System.Data.SqlClient.SqlCommandSet+LocalCommand"); 

aber Activator.CreateInstance wirft eine Ausnahme, wenn ich versuche, es zu instanziieren:

object item = Activator.CreateInstance(localCmdType, 
    new object[] { commandText, parameters, num7, commandType }); 

System.MissingMethodException: Constructor auf Typ ‚System .Data.SqlClient.SqlCommandSet + LocalCommand 'nicht gefunden.

Die Konstruktorargumente stimmen mit der Signatur überein, die in Reflector angezeigt wird. Wird eine private Klasse mit einem internen Core neugestartet, der von einer anderen CreateInstance-Überladung unterstützt wird?

Antwort

18

Mein erster Gedanke wäre, die ConstructorInfo mit ConstructorInfo constructorInfo = Type.GetConstructor(), und dann constructorInfo.Invoke() das zu bekommen. Ich vermute, dass Activator.CreateInstance es schwer macht, Konstruktoren aufzurufen, auf die man normalerweise keinen Zugriff hätte, obwohl ich mich nicht daran erinnern kann, es selbst zu versuchen.

+2

Die docs sagen CreateInstance nur öffentliche Konstrukteuren vor 2.0sp1 nennt. Danach gibt es eine Reihe von Berechtigungen, die notwendig sind. –

+1

Guter Aufruf von GetConstructor(), das funktioniert. Ich finde es merkwürdig, wenn man bedenkt, dass der GetConstructor-Aufruf einer der Activator.CreateInstance() - Überladungen sehr ähnlich sieht. –

18

Ich habe es auf diese Weise zu arbeiten:

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

Der Trick nach dem Konstruktor zu gehen war speziell mit GetConstructor eher dann in den Ergebnissen der GetConstructors zu finden versuchen. Stelle dir das vor.

+0

Danke für das Beispiel! –

+0

Kann es sein, dass dies in PCL nicht verfügbar ist? –

10

Ich könnte ein wenig spät reagieren, aber ich stieß auf ein ähnliches Problem, das in dieses Thema passt. Ich wollte einen nicht öffentlichen Konstruktor mit Activator.CreateInstance instanziieren und Argumente übergeben.

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

Der schwierige Teil war die verbindlichen Flags. Mein erster Instinkt war, BindingFlags.CreateInstance | zu verwenden BindingFlags.NonPublic, jedoch wurde eine Ausnahme ausgelöst: MissingMethodException Constructor für den Typ 'Node' wurde nicht gefunden. Genießen Sie

+0

Das scheitert für mich mit dem Fehler, den Sie beschreiben, aber seltsamerweise funktioniert Andrew Hares Antwort, obwohl beide Antworten dieselben verbindlichen Flags haben. – Jerther

+0

Funktioniert einfach nicht. Wie Jerther sagte, hat Andrew Hare's Antwort. –

+0

Arbeitete wie ein Charme für mich! Ich versuchte auch '' 'BindingFlags.CreateInstance | BindingFlags.NonPublic''' und hat dieselbe Fehlermeldung erhalten.Ändern zu '' 'BindingFlags.Instance | BindingFlags.NonPublic''' hat es geschafft !! – Kaboo

0

Trick ist, um sicherzustellen, das Recht CreateInstance Überlastung zu verwenden:

// WRONG 
... Activator.CreateInstance(
     type, 
     BindingFlags.Instance 
     | BindingFlags.NonPublic 
    ); 

Dies ruft die params Überlastung, die Instance | Public | CreateInstance ausfällt und Ihre Bindung Flaggen werden als Argumente an den Konstruktor übergeben werden, was die vage MissingMethodException.

Verwenden Sie auch Instance | Public | NonPublic, wenn Sie nicht sicher, ob der Sicht des Konstrukteurs sind:

// right 
... Activator.CreateInstance(
     type, 
     BindingFlags.Instance 
     | BindingFlags.Public 
     | BindingFlags.NonPublic, 
     null, 
     new object[] { }, // or your actual constructor arguments 
     null 
    );