2011-01-16 18 views
1

Grüße! Ich habe (ein bisschen) mit C# und seinen Baugruppen herumalbern. Und so habe ich eine so interessante Funktion gefunden wie dynamische Lade-Assemblies und das Aufrufen der Klassenmitglieder. Ein wenig von Google und hier bin ich, schreibe eine Art "Assembly Explorer". (Ich habe einige Teile des Codes von here, here und here verwendet und keiner von ihnen gab irgendwelche der erwarteten Ergebnisse).C# 'konnte nicht gefunden werden' bestehende Methode

Aber ich habe einen kleinen Fehler gefunden: als ich versuchte, Klassenmethode von Assembly aufzurufen habe ich geladen, Anwendung ausgelöst MissingMethod Ausnahme. Ich bin sicher, dass DLL i Laden bin enthält Klassen und Methoden i bin tryin' aufzurufen (meine App sorgt für mich als auch RedGate .NET Reflector):

alt text

Der Hauptanwendungscode scheint um in Ordnung zu sein und ich fange an zu denken, wenn ich mit meiner DLL falsch war ... Ah, und ich habe beide Projekte in eine Lösung gebracht, aber ich denke nicht, dass es irgendwelche Probleme verursachen kann. Und ja, DLL-Projekt hat 'Klassenbibliothek' als Ziel, während die Hauptanwendung 'Konsolenanwendungsziel' hat.

Also, die Frage ist: Was ist los mit ihnen?

Hier sind einige Quellcode:

DLL Quelle:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ClassLibrary1 
{ 
    public class Class1 
    { 
     public void Main() 
     { 
      System.Console.WriteLine("Hello, World!"); 
     } 
    } 
} 

Hauptanwendung Quelle:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Assembly asm = Assembly.LoadFrom(@"a\long\long\path\ClassLibrary1.dll"); 

      try 
      { 
       foreach (Type t in asm.GetTypes()) 
       { 
        if (t.IsClass == true && t.FullName.EndsWith(".Class1")) 
        { 
         object obj = Activator.CreateInstance(t); 
         object res = t.InvokeMember("Main", BindingFlags.Default | BindingFlags.InvokeMethod, null, obj, null); // Exception is risen from here 
        } 
       } 
      } 
      catch (Exception e) 
      { 
       System.Console.WriteLine("Error: {0}", e.Message); 
      } 

      System.Console.ReadKey(); 
     } 
    } 
} 

UPD: für einen Fall gearbeitet - wenn DLL Methode braucht keine Argumente:

DLL-Klasse (funktioniert auch, wenn Methode ist nicht statisch):

public class Class1 
{ 
    public static void Main() 
    { 
     System.Console.WriteLine("Hello, World!"); 
    } 
} 

Methode invoke Code:

object res = t.InvokeMember("Main", BindingFlags.Default | BindingFlags.InvokeMethod, null, null, null); 
+0

Würde mich überprüfen: Sie können auf ein Objekt eine statische Methode über invoke nennen? –

+0

Werfen Sie einen Blick auf die Kommentare unten - es gibt keine Unterschiede mit oder ohne 'statische', Argumente oder was auch immer. – shybovycha

Antwort

3

Sie erhalten wahrscheinlich die InvokeMember() - Argumente falsch.Hier ist ein Beispiel, das funktioniert:

using System; 
using System.Reflection; 

class Program { 
    static void Main(string[] args) { 
     if (args.Length > 0) Console.WriteLine(args[0]); 
     else { 
      Assembly asm = Assembly.LoadFrom(Assembly.GetEntryAssembly().Location); 
      foreach (Type t in asm.GetTypes()) { 
       if (t.IsClass == true && t.FullName.EndsWith(".Program")) { 
        //object obj = Activator.CreateInstance(t); 
        object res = t.InvokeMember("Main", 
         BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod, 
         null, null, 
         new object[] { new string[] { "Invoked" } }); 
       } 
      } 
     } 
    } 
} 
  • Hinweis, wie die Methode Main() nicht öffentlich ist, so BindingFlags.NonPublic
  • Hinweis, wie die Methode Main() statisch ist, so BindingFlags.Static
  • Aus dem gleichen Grund, für die Ziel null übergeben Parameter
  • Aus dem gleichen Grund ist CreateInstance nicht notwendig
  • Hinweis, wie die Methode Main() einen String [] Argument, Sie muss übergeben werden, um Reflection zu erhalten, um die richtige Methodenüberladung zu finden.

folgen der gleichen Logik für Ihre Methode Main():

   object res = t.InvokeMember("Main", 
        BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, 
        null, obj, 
        new object[] { }); 
+0

Ja, danke! Ich habe mich geirrt, als ich String Array als Argumentliste übergeben habe (siehe InvokeMember()). Vielen Dank! =) – shybovycha

4

Warum craeting Sie eine Instanz (Activator.CreateInstance(t)), um eine statische Methode aufrufen ???? Es sollte sein:

t.InvokeMember(
    "Main", 
    BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, 
    null, 
    null, 
    new object[] { new string[0] } 
); 

Auch diese Methode wie definiert gibt keinen Wert zurück, so dass keine Rückgabevariable zugewiesen werden muss.

Und um alle zu Missverständnisse auszuräumen ich eine volle Arbeits Demo hier erstellt haben: http://www.mediafire.com/?n7h9b8ghomfv17d

+0

Nicht statisch, noch üblich, haben keine Ergebnisse ergeben. Die gleiche Ausnahme. Also mit deinem Code. – shybovycha

+0

Beachten Sie außerdem, dass der Asker keine Argumente für die Methode lieferte. –

+0

@shybovicha, von dem, was ich sehen kann 'Class1.Main' ist eine statische Methode. Außerdem haben Sie das letzte Argument bemerkt, das ich an den Aufruf 'InvokeMember' übergebe: 'new object [] {new string [0]}' anstelle von 'null'. –

2

Der letzte Parameter zu InvokeMember ist ein Array von Objekten, die Argumente der Methode enthält.

Sie übergeben null dort, sollten Sie ein Array von Objekten übergeben, die ein einzelnes Element (ein Array von Zeichenfolgen) enthalten.

+0

Lesen Sie Kommentare über – shybovycha

+0

Oh, sorry, ich habe die letzten zwei Zeilen Ihres Beitrags verpasst. .. = ( – shybovycha

Verwandte Themen