2011-01-16 16 views
1

ご挨拶! 私はC#とそのアセンブリで(少し)騙してきました。ダイナミックローディングアセンブリやそのクラスメンバを呼び出すという面白い機能が見つかりました。 googleのビットとここで私は、いくつかの種類の 'アセンブリエクスプローラ'を書いています。 (私はherehereおよびhereからコードの一部を使用していますが、期待した結果はありませんでした)。C# '見つかりませんでした'既存のメソッド

しかし、私は小さなバグを発見しました。私がロードしたアセンブリからクラスメソッドを呼び出そうとしたとき、アプリケーションはMissingMethod例外を発生させました。メインのアプリケーションコードは思わ

alt text

:私は、私はロードだDLLは私が(私のアプリは、私だけでなく、レッドゲートの.NETリフレクターを保証します)呼び出すことトラインだクラスやメソッドが含まれていると確信しています大丈夫だと私は私のDLLで間違っていた場合、私は考え始めます...ああ、私は1つのソリューションに両方のプロジェクトを入れましたが、私はそれが問題を引き起こす可能性があるとは思わない。そして、はい、DLLプロジェクトには「クラスライブラリ」のターゲットがあり、メインアプリケーションには「コンソールアプリケーション」のターゲットがあります。

質問:何が問題なのですか?ここで

は、いくつかのソースコードです:

DLLソース:

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

メインアプリケーションソース:

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:は1ケースのために働いていた - DLLメソッドは引数をとりません:

DLLクラス(メソッドが静的でない場合も動作します):あなたがするために、(Activator.CreateInstance(t))インスタンスをcraetingているのはなぜ

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

は自分自身をチェックする必要があります:あなたは、オブジェクトの呼び出しを経由して静的メソッドを呼び出すことができますか? –

+0

以下のコメントを見てください。「静的な」引数やその他のものとの違いはありません。 – shybovycha

答えて

3

InvokeMember()引数が間違っている可能性があります。ここで働くのサンプルです:

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" } }); 
       } 
      } 
     } 
    } 
} 
  • main()メソッドが公開されていないか注意、メイン()メソッドは、これBindingFlags.Static
  • 静的であるかようBindingFlags.NonPublic
  • 注意同じ理由で
  • 、同じ理由でターゲットパラメータ
  • のためにnullを渡す、のCreateInstanceが必要
  • 注意しない主()メソッドを使用するには、文字列[]引数を取る方法Reflectionが正しいメソッドオーバーロードを見つけるために渡す必要があります。

自分のメインのために同じロジックを実行します()メソッド:

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

ええ、ありがとう!引数リストとして文字列配列を渡している間に間違っていた(InvokeMember()を参照)。 – shybovycha

4

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

方法は、コードを呼び出します静的メソッドを呼び出す

また、定義されているこのメソッドは値を返さないため、戻り変数を割り当てる必要はありません。

そして、私はここで完全に動作するデモを作成したすべての誤解をクリアするために:http://www.mediafire.com/?n7h9b8ghomfv17d

+0

静的ではなく、通常の結果もありません。同じ例外。だからあなたのコード。 – shybovycha

+0

また、質問者がメソッドの引数を指定していないことに注意してください。 –

+0

@shybovycha、私が見ることができるものから 'Class1.Main'は静的メソッドです。また、 'InvokeMember'呼び出しに渡している最後の引数、' null'の代わりに 'new {new string [0]}'に気付きました。 –

2

InvokeMemberの最後のパラメータは、メソッドの引数を含むオブジェクトの配列です。

あなたはnullを渡していますが、1つの要素(文字列の配列)を含むオブジェクトの配列を渡す必要があります。

+0

上記のコメントを読む – shybovycha

+0

ああ、ごめんなさい、私はあなたの投稿の最後の2行を見逃しました。 .. =( – shybovycha

関連する問題