2017-07-26 12 views
3

は、WinFormsのアプリケーションからこのコードサンプルを考えてみましょう:メソッドの呼び出しが引数の例外で失敗するのはなぜですか?

public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      object[] parms = new object[1]; 
      parms[0] = "foo"; 

      DoSomething(parms); 
     } 

     public static string DoSomething(object[] parms) 
     { 
      Console.WriteLine("Something good happened"); 
      return null; 
     } 
    } 

期待どおりボタン1をクリックすると、それはそれは、コンソールに「良い起こった何か」を印刷し、動作します。今では、リフレクションを使用してDoSomethingを呼び出すことを除いて同じである。このサンプルコードを検討

public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      object[] parms = new object[1]; 
      parms[0] = "foo"; 

      System.Reflection.MethodInfo mi = typeof(Form1).GetMethod("DoSomething"); 
      mi.Invoke(null, parms); 

     } 

     public static string DoSomething(object[] parms) 
     { 
      Console.WriteLine("Something good happened"); 
      return null; 
     } 
    } 

それはラインmi.Invoke(null, parms)(タイプのオブジェクト上System.ArgumentExceptionをスロー「は可能System.String」に変換できませんタイプ「System.Objectの[]」。)

PARMSは明らかオブジェクト配列であり、doSomethingののメソッドのシグネチャは、明らかにオブジェクト配列を期待しています。なぜ、最初のオブジェクトを配列から引き出し、代わりにそれを渡そうとするのですか?

それとも私は理解していない何か他のことがありますか?

答えて

7

MethodInfo.Invokeは、オブジェクト配列、を期待して動作します方法。オブジェクト配列の最初の引数は最初の引数、配列の2番目のオブジェクト、2番目のメソッドなどです

メソッドの最初の引数をobject[]にしたいので、最初のオブジェクトMethodInfo.Invokeに渡すオブジェクト配列には、DoSomethingが使用する配列を表すオブジェクト配列があります。

+1

これは今完璧な理にかなって - もちろんそれはそのように動作します。キーボードから数分歩く時間:-) – GojiraDeMonstah

2
object[] parms = new object[1]; 
parms[0] = "foo"; 

:問題です

public static string DoSomething(object[] parms) 

。最初のパラメータはstringではなく、object[]です。 Invokeに渡されたobject[]は、の各パラメータを順番にと表します。したがって、長さが1の文字列のobject[]static string DoSomething(string s)と一致しますが、一致しません。署名を変更するか、値をラップします。率直に言って、私は署名を変更することをお勧めすることはここに良いアイデアですが、:

parms[0] = new object[] { "foo" }; 

もオブジェクト配列内の各オブジェクトが引数に相当する

1

MethodInfo.Invokeは、パラメータとしてオブジェクトのアレイは、アレイ内の各オブジェクトは、異なるパラメータであろう関数に複数の引数を渡すことを期待します。

あなたの関数は、オブジェクト配列ではなく文字列である引数として渡すオブジェクト配列も期待しています。

あなたは、別の配列にその配列をラップする必要があり、このように起動は、最初の配列のラップを解除し、通話のための最初のパラメータとして内部配列を使用します。

mi.Invoke(null, new object[]{ parms }); 
1

parms is clearly an object array, and DoSomething's method signature is clearly expecting an object array.

はいそれはオブジェクト配列を期待しています。あなたはこの渡したときしかし:

object[] parms = new object[1]; 

をあなたは[0] DoSomethingの最初の引数で、より多くのアイテムがparmsその後、PARMSであった場合は、[1]第二になりますPARMSように、これらはDoSomethingの引数ですと言っています議論などがあります。

明らかにDoSomethingのための最初の引数はstring(PARMS [0])ではな​​いので、このエラーが発生します:

It throws an System.ArgumentException on the line mi.Invoke(null, parms) (Object of type 'System.String' cannot be converted to type 'System.Object[]'.)

関連する問題