2010-02-04 8 views
152

Ich versuche, eine Methode über Reflektion mit Parametern aufzurufen, und ich bekomme:Reflexion: Wie Invoke-Methode mit Parametern

Objekt übereinstimmen Typ Ziel nicht

Wenn ich eine Methode aufrufen, ohne Parameter, es funktioniert gut. Basierend auf dem folgenden Code, wenn ich die Methode Test("TestNoParameters") aufrufen, funktioniert es gut. Wenn ich jedoch Test("Run") rufe, bekomme ich eine Ausnahme. Stimmt etwas nicht mit meinem Code?

My ursprünglichen Zweck war ein Array von Objekten passieren z.B. public void Run(object[] options) aber das hat nicht funktioniert und ich versuchte etwas einfacher, z. String ohne Erfolg.

Antwort

182

Ändern Sie "methodInfo" in "classInstance", genau wie im Aufruf mit dem null-Parameterarray.

result = methodInfo.Invoke(classInstance, parametersArray); 
+24

Das ist, was wir hier für;) – womp

+0

Dies funktioniert, außer, wenn sie mit einer Instanz einer Remote-Baugruppe arbeiten. Das Problem war, dass es denselben Fehler ausgibt, der nicht sehr hilfreich ist. Ich habe mehrere Stunden damit verbracht, es zu reparieren, und habe eine neue allgemeine Lösung sowohl für meinen Fall als auch für den hier vorgestellten veröffentlicht. Falls jemand es brauchen könnte :) –

+1

Wenn die Parameter von mehreren Typen sind, wie sollte das Array aussehen? eine Reihe von Objekten? –

18

Ein grundlegender Fehler ist hier:

result = methodInfo.Invoke(methodInfo, parametersArray); 

Sie sind auf einer Instanz von MethodInfo die Methode aufgerufen wird. Sie müssen eine Instanz des Objekttyps übergeben, auf den Sie zugreifen möchten.

result = methodInfo.Invoke(classInstance, parametersArray); 
23

Sie haben einen Fehler genau dort

result = methodInfo.Invoke(methodInfo, parametersArray); 

es

result = methodInfo.Invoke(classInstance, parametersArray); 
8

Die bereitgestellte Lösung funktioniert nicht von einer Remote-Assembly geladen für Instanzen von Typen sein sollte. Um dies zu tun, ist hier eine Lösung, die in allen Situationen funktioniert, die eine explizite Typ-Neuzuordnung des durch den CreateInstance-Aufruf zurückgegebenen Typs beinhaltet.

So muss ich meine classInstance erstellen, da sie sich in einer Remote-Assembly befand.

// sample of my CreateInstance call with an explicit assembly reference 
object classInstance = Activator.CreateInstance(assemblyName, type.FullName); 

Aber selbst mit der oben angegebenen Antwort erhalten Sie immer noch den gleichen Fehler. Hier ist, wie es geht:

// first, create a handle instead of the actual object 
ObjectHandle classInstanceHandle = Activator.CreateInstance(assemblyName, type.FullName); 
// unwrap the real slim-shady 
object classInstance = classInstanceHandle.Unwrap(); 
// re-map the type to that of the object we retrieved 
type = classInstace.GetType(); 

Dann wie die anderen hier genannten Benutzer tun.

3

würde ich es so verwenden, seinen Weg kürzer und es wird keine Probleme

 dynamic result = null; 
     if (methodInfo != null) 
     { 
      ParameterInfo[] parameters = methodInfo.GetParameters(); 
      object classInstance = Activator.CreateInstance(type, null); 
      result = methodInfo.Invoke(classInstance, parameters.Length == 0 ? null : parametersArray); 
     } 
0
Assembly assembly = Assembly.LoadFile(@"....bin\Debug\TestCases.dll"); 
     //get all types 
     var testTypes = from t in assembly.GetTypes() 
         let attributes = t.GetCustomAttributes(typeof(NUnit.Framework.TestFixtureAttribute), true) 
         where attributes != null && attributes.Length > 0 
         orderby t.Name 
         select t; 

     foreach (var type in testTypes) 
     { 
      //get test method in types. 
      var testMethods = from m in type.GetMethods() 
           let attributes = m.GetCustomAttributes(typeof(NUnit.Framework.TestAttribute), true) 
           where attributes != null && attributes.Length > 0 
           orderby m.Name 
           select m; 

      foreach (var method in testMethods) 
      { 
       MethodInfo methodInfo = type.GetMethod(method.Name); 

       if (methodInfo != null) 
       { 
        object result = null; 
        ParameterInfo[] parameters = methodInfo.GetParameters(); 
        object classInstance = Activator.CreateInstance(type, null); 

        if (parameters.Length == 0) 
        { 
         // This works fine 
         result = methodInfo.Invoke(classInstance, null); 
        } 
        else 
        { 
         object[] parametersArray = new object[] { "Hello" }; 

         // The invoke does NOT work; 
         // it throws "Object does not match target type"    
         result = methodInfo.Invoke(classInstance, parametersArray); 
        } 
       } 

      } 
     } 
0

gebe ich versuchte mit allen vorgeschlagenen Antworten oben zu arbeiten, aber nichts für mich zu arbeiten scheint. Also versuche ich zu erklären, was hier für mich funktioniert hat.

Ich glaube, wenn Sie eine Methode wie die Main unten oder sogar mit einem einzigen Parameter, wie in Ihrer Frage anrufen, müssen Sie nur noch die Art des Parameters string-object für diese

class Class1 
{ 
    public static void Execute(object[] str) 
    {...} 
} 
zu arbeiten ändern

Dann müssen Sie das ParameterArray in einem Objekt-Array wie folgt übergeben, während Sie es aufrufen.

MethodInfo mi = typeInstance.GetType().GetMethod("Execute"); 
ParameterInfo[] parameters = mi.GetParameters(); 
object classInstance = Activator.CreateInstance(typeInstance.GetType(), null); 

if (parameters.Length == 0) 
{ 
    // This works fine 
    var result = mi.Invoke(classInstance, null); 
} 
else 
{ 
    object[] parametersArray = new object[] { "Hello","bye" }; 
    var result = mi.Invoke(classInstance,new object[] { parametersArray }); 
} 

hoffe, das hilft