コンソールアプリケーションはこんな感じですね
namespace SimpleApp01
{
class Program
{
static void Main(string[] args)
{
}
}
}
クラスが非公開で、メイン関数が引数ありのstaticメソッドになっています。
つい、こんな風に書きたくなりませんか?
コンソールアプリケーションの引数は、string[] args なので、それを引数に渡したら動くような気がしちゃいます。
でも、実際にはこれではmethod.invokeでエラーとなり、
System.Reflection.TargetParameterCountException: 'パラメーター カウントが一致しません。'(parameter count mismatch)
が発生します。
つい、こんな風に書きたくなりませんか?
var asm = Assembly.Load("SimpleApp01");
var t = asm.GetType("SimpleApp01.Program");
var method = t.GetMethod("Main", BindingFlags.Static | BindingFlags.NonPublic);
// コンソールからの引数を設定
string[] args = new string[] { "aaa", "bbb" };
method.Invoke(null, args);
コンソールアプリケーションの引数は、string[] args なので、それを引数に渡したら動くような気がしちゃいます。
でも、実際にはこれではmethod.invokeでエラーとなり、
System.Reflection.TargetParameterCountException: 'パラメーター カウントが一致しません。'(parameter count mismatch)
が発生します。
Invokeの第2引数には、実際のメソッドの引数を指定する必要があります。
上記のargsを指定するということは
static void Main (string paramA, string paramB)
のようなメソッドの呼び出しをすることになってしまいます。
なので、実際は以下のようになります。
var asm = Assembly.Load("SimpleApp01");
var t = asm.GetType("SimpleApp01.Program");
var method = t.GetMethod("Main", BindingFlags.Static | BindingFlags.NonPublic);
// コンソールからの引数を設定
string[] args = new string[] { "aaa", "bbb" };
var p = new object[] { args };
method.Invoke(null, p);
VisualStudioの単体テストプロジェクトの場合PrivateTypeを使用することもできます。
その場合も同様にこんな感じになります。
var asm = Assembly.Load("SimpleApp01");
var t = asm.GetType("SimpleApp01.Program");
// PrivateTypeによる呼び出し
string[] args = new string[] { "aaa", "bbb" };
var p = new object[] { args };
PrivateType pt = new PrivateType(t);
pt.InvokeStatic("Main", p);