none
ReflectionでTargetParameterCountException:パラメータ カウントが一致しません。 RRS feed

  • 質問

  • 行いたい事

    AAA.DLL の Class1.MathodAを 呼び出そうとしています。

     

    コード ブロック

    Project AAA

     

     public class Class1 : IReflectionTest
     {
        public Class1()
        {
        }

        public bool MethodA(string [] param)
        {
         for(int i = 0; i < param.Length; i++ )
         {
          Console.WriteLine(param[i]);
         }
         return(true);
      }

      public bool MethodB(out string [] param)
      {
       param = new string[5];
       param[0] = "@10000";
       param[1] = "@20000";
       param[2] = "@30000";
       param[3] = "@40000";
       param[4] = "@50000";
       return(true);
      }
     }

     

     public interface IReflectionTest
     {
      bool MethodA(string [] param);
      bool MethodB(out string [] param);
     }

     

     

    呼び出す側のコード

     

    コード ブロック

      private void button1_Click(object sender, System.EventArgs e)
      {
       string [] paramA = {"file1","file2","file3"};
       object [] parameterA = new object[paramA.Length];
       parameterA = paramA;

     

       Assembly assembly = Assembly.LoadFrom("絶対パスで指定してます\AAA.DLL");
       Type classType = assembly.GetType("AAA.Class1");
       object classInstance = Activator.CreateInstance(classType);

     

       MethodInfo methodInfo = classType.GetMethod("MethodA");
       methodInfo.Invoke(classInstance, parameterA);

      }

     

     

    最後の行の methodInfo.Invoke で

     

    System.Reflection.TargetParameterCountException: パラメータ カウントが一致しません。

    となってしまいます。

     

    何か根本的な間違いをしているのでしょうか、ご指摘ください。

    2008年1月16日 1:53

回答

  •  いくみ さんからの引用

    >object[] { string[] }

    すみません。この箇所がよく理解出来ません。

     

    MethodInfo.Invoke(object  obj, object [] parameters)

    となっていますので

    >Invoke は引数の配列をとります。

    第二引数が 引数の配列と解釈しています。

     

    そのとおりです。

    「引数の配列」をとります。

    「配列の引数」ではありません。

    意味が違いますよね。

     

    Invokeは引数を配列として渡します。

    引数の一つが配列であったばあい、object配列の要素として配列を指定します。

     

    「配列」と、「配列の配列」と、違いますよね?

     

    渡したいのは「stringの配列」で、

    Invokeが受け付けるのは引数を並べたobject型の配列です。

    stringの配列が第一要素に入ったobject型の配列を渡すのが正解で、

    それを「object[] { string[] }」と表現しました。

     

     

     

    2008年1月16日 4:47

すべての返信

  • Invoke は引数の配列をとります。

    個の場合、MethodAの引数の配列です。

    MethodAの引数は一つで、それは配列であり、string[]です。

    なら、object[] { string[] }を渡してあげなければいけません。

     

    void MethodB( string, string, string )

    みたいな関数を呼び出す場合も、同じInvokeで呼び出せるはずですよね?

     

    自分のケースだけでなく、

    メソッドを使う他のケースや、

    作った人が何を考えて作ったかを推測するとわかりやすいと思います。

    2008年1月16日 2:42
  • れいさん レスありがとうございます。

    >object[] { string[] }

    すみません。この箇所がよく理解出来ません。

     

    MethodInfo.Invoke(object  obj, object [] parameters)

    となっていますので

    >Invoke は引数の配列をとります。

    第二引数が 引数の配列と解釈しています。

     

    Typeもobjectの配列で渡しているのに パラメータカウント?

    個数が何故関係あるのか分からないです。

     

    2008年1月16日 3:57
  • >Typeもobjectの配列で渡しているのに パラメータカウント?

    >個数が何故関係あるのか分からないです。

     

    あなたが実際に渡しているのは、paramA自体です。

    {"file1","file2","file3"}

    です。

    つまり、文字列引数3個を受け取るメソッド用の渡し方になってます。

    個数も違いますよね?

     

    MethodAは、「文字列配列」を「ひとつ」受け取るメソッドです。

    2008年1月16日 4:04
  •  いくみ さんからの引用

    >object[] { string[] }

    すみません。この箇所がよく理解出来ません。

     

    MethodInfo.Invoke(object  obj, object [] parameters)

    となっていますので

    >Invoke は引数の配列をとります。

    第二引数が 引数の配列と解釈しています。

     

    そのとおりです。

    「引数の配列」をとります。

    「配列の引数」ではありません。

    意味が違いますよね。

     

    Invokeは引数を配列として渡します。

    引数の一つが配列であったばあい、object配列の要素として配列を指定します。

     

    「配列」と、「配列の配列」と、違いますよね?

     

    渡したいのは「stringの配列」で、

    Invokeが受け付けるのは引数を並べたobject型の配列です。

    stringの配列が第一要素に入ったobject型の配列を渡すのが正解で、

    それを「object[] { string[] }」と表現しました。

     

     

     

    2008年1月16日 4:47
  • なちゃさん レスありがとうございます。

     

    >あなたが実際に渡しているのは、paramA自体です。

    この一文だけが、私にはピンと来ました。

     

    そして

     

    れいさん レスありがとうございます。

     

    >「引数の配列」をとります。

    >「配列の引数」ではありません。

    >意味が違いますよね。

     

    これで完全に分かりました。

     

    >Invokeが受け付けるのは引数を並べたobject型の配列です。

    成る程、まったく勘違いしていた訳ですね。

     

    お二人のこの5行にて理解できました。

     

    Hongliangさん レスありがとうございます。

    引用の箇所は つまり、なちゃさん指摘の object[]に型を変えた

    所で結局は string[] なんだよ という指摘なのでしょうか。

     

    コード ブロック

      private void button1_Click(object sender, System.EventArgs e)
      {
       string [] paramA = {"file1","file2","file3"};
       object [] parameterA = new object[1];
       object [] parameterB = new object[1];
       parameterA[0] = paramA;


     

       Assembly assembly = Assembly.LoadFrom("絶対パスで指定してます\AAA.DLL");
       Type classType = assembly.GetType("AAA.Class1");
       object classInstance = Activator.CreateInstance(classType);

     

       MethodInfo methodInfoA = classType.GetMethod("MethodA");
       methodInfoA.Invoke(classInstance, parameterA);

     

       MethodInfo methodInfoB = classType.GetMethod("MethodB");

       methodInfoB.Invoke(classInstance, parameterB);

     

       string [] paramB = (string[])parameterB[0];
       for( int i = 0 ; i < paramB.Length; i++)
       {
        Console.WriteLine(paramB[i]);
       }

      }

     

     

    実行に成功しました。

    >object [] parameterB = new object[1];

    この行とか、なんか小細工っぽくてスマートに書けてない気がしますが・・・

    みなさんの指摘で理解できました。

    ありがとうございました。

     

    2008年1月16日 6:55
  •  いくみ さんからの引用

    >object [] parameterB = new object[1];

    この行とか、なんか小細工っぽくてスマートに書けてない気がしますが・・・

     

    ひとそれぞれですので、

    あまり気にしてもしょうがないですし、

    私には十分にスマートにかけてると思います。

     

    見づらいのでしたら他にも書き方はあると思います。

    1回しか使わないのであれば、

    methodInfoA.Invoke(classInstance, new Object[] { paramA } );

    と書くと、変数名を考えなくても済みます。

    2008年1月16日 7:14
  • れいさん レスありがとうございます。

    >methodInfoA.Invoke(classInstance, new Object[] { paramA } );

    こっちのがよけいな変数を増やさなくてスマートですね!

    ありがとうございます。

     

    2008年1月16日 8:44