outパラメータメソッドをリフレクションで実行するときのTips

投稿者: | 2016-12-07

タイトルの通り、outパラメータを受け取るメソッドをリフレクションで実行し、その実行結果を引数に渡したオブジェクトから取り出そうとしたらうまくいかなかったので、少し調べてまとめました。

サンプルコートと失敗例と成功例

outパラメータを受け取るメソッドのサンプルコートは以下の通りです。

public class OutTest
{
    public void OutMethod(out string str)
    {
        str = "d.yama";
    }
}

public class Program
{
    static void Main(string[] args)
    {
        OutTest obj = new OutTest();
        string sample = "";
        obj.OutMethod(out sample);

        Console.WriteLine(sample);    // d.yamaと出力される
    }
}

リフレクションでメソッドを実行し、その結果をoutパラメータから取り出すことを試みます。
まずは私の失敗例です。

public class Program
{
    static void Main(string[] args)
    {
        OutTest obj = new OutTest();
        string sample = "";

        Type type = obj.GetType();
        MethodInfo methodInfo = type.GetMethod("OutMethod");
        object[] parameter = { sample };
        methodInfo.Invoke(obj, parameter);

        Console.WriteLine(sample);    // 空文字が出力される
        Console.ReadLine(); 
    }
}

通常呼び出し時と同じように、オブジェクトを渡してあげればそこから取得できると思ったのですが、失敗してしまいました。
続いて成功例です。

public class Program
{
    static void Main(string[] args)
    {
        OutTest obj = new OutTest();

        Type type = obj.GetType();
        MethodInfo methodInfo = type.GetMethod("OutMethod");
        object[] parameter = { null };
        methodInfo.Invoke(obj, parameter);

        Console.WriteLine(parameter[0]);    // d.yamaと出力される
    }
}

上記のように、Invokeに渡すobject配列の該当箇所にnullを指定すれば、メソッド実行後に配列にアクセスすれば結果を取得できます。

そもそもどうしてリフレクションを使っていたのか

Unityプロジェクトでテストコードを書いており、privateメソッドをテストしようとしたのが事の発端です。

UnityエディタにはNUnitが組み込まれているので、流されるままそちらを使用していました。NUnitではprivateメンバをテストするには、リフレクションを使ってメソッドにアクセスする、という記事をちらほら見かけたので私もそれに倣っていました。その時ちょうどoutパラメータを受け取るメソッドをテストしようとしており、上記のように失敗し詰まってしまい調査を行ったという次第です。

せっかくだからブログに書いておこうと思い(何となくpost数も稼ぎたかったし)、さらにいろいろと調べてみたら、MSTestを使えばリフレクションを使わなくてもprivateメンバをテストできるようです。

ほうほうなるほど、それではMSTestに乗り換えてみるかな、Unityエディタからは実行できなさそうだけど、と思っていたら以下の記事を見つけました。

どうやらprivateメンバをユニットテストするというのには否定的な意見も多いようです。