【C#】リフレクションを利用してメソッド名を文字列指定で動的に呼び出す

通常、メソッドの呼び出しは instance.MethodName() のように記述しますが、プラグインシステムや動的なスクリプト実行など、実行時になるまで呼び出すべきメソッド名が分からないケースがあります。

このような場合、Type.GetMethodMethodInfo.Invoke を組み合わせることで、メソッド名を文字列で指定して実行することが可能です。

目次

Invokeメソッドによる動的実行の実装

以下のサンプルコードでは、電卓クラス(Calculator)に定義された計算メソッドを、文字列(”Add” や “Multiply”)で指定して呼び出す処理を実装しています。引数もオブジェクト配列として動的に渡します。

サンプルコード

using System;
using System.Reflection;

public class Program
{
    public static void Main()
    {
        // 1. メソッドを持つクラスのインスタンス生成
        var calc = new Calculator();

        // 2. クラスの型情報を取得
        Type targetType = calc.GetType();

        Console.WriteLine("--- 動的なメソッド呼び出し ---");

        // 例1: Addメソッド(足し算)を呼び出す
        // 引数として 10 と 20 を渡す
        CallDynamicMethod(targetType, calc, "Add", new object[] { 10, 20 });

        // 例2: Subtractメソッド(引き算)を呼び出す
        // 引数として 50 と 15 を渡す
        CallDynamicMethod(targetType, calc, "Subtract", new object[] { 50, 15 });

        // 例3: Multiplyメソッド(掛け算)を呼び出す
        CallDynamicMethod(targetType, calc, "Multiply", new object[] { 5, 5 });

        // 存在しないメソッドを指定した場合の挙動確認
        CallDynamicMethod(targetType, calc, "Divide", new object[] { 100, 2 });
    }

    /// <summary>
    /// 指定された名前のメソッドをリフレクションで実行する
    /// </summary>
    /// <param name="type">型情報</param>
    /// <param name="instance">実行対象のインスタンス</param>
    /// <param name="methodName">メソッド名</param>
    /// <param name="args">引数配列</param>
    public static void CallDynamicMethod(Type type, object instance, string methodName, object[] args)
    {
        // 1. メソッド情報を取得 (publicなインスタンスメソッドを検索)
        MethodInfo methodInfo = type.GetMethod(methodName);

        if (methodInfo == null)
        {
            Console.WriteLine($"[エラー] メソッド '{methodName}' は見つかりませんでした。");
            return;
        }

        try
        {
            // 2. メソッドを実行 (Invoke)
            // 第一引数: インスタンス, 第二引数: 引数の配列
            object result = methodInfo.Invoke(instance, args);

            Console.WriteLine($"実行: {methodName}({string.Join(", ", args)}) => 結果: {result}");
        }
        catch (ArgumentException)
        {
            Console.WriteLine($"[エラー] '{methodName}' の引数が一致しません。");
        }
    }
}

// 計算機能を提供するクラス
public class Calculator
{
    public int Add(int a, int b) => a + b;
    
    public int Subtract(int a, int b) => a - b;
    
    public int Multiply(int a, int b) => a * b;
    
    // Divideメソッドは意図的に定義していません
}

解説と技術的なポイント

1. Type.GetMethodメソッド

指定した名前を持つ public メソッドの情報を MethodInfo オブジェクトとして取得します。 メソッドのオーバーロード(同名で引数が異なるメソッド)が存在する場合は、このメソッドだけでは特定できないため、引数の型を指定する別のオーバーロード(GetMethod(string name, Type[] types))を使用する必要があります。

2. MethodInfo.Invokeメソッド

取得したメソッド情報に基づいて、実際に処理を実行します。

  • 第一引数 (obj): メソッドを実行する対象のインスタンス。static メソッドの場合は null を指定します。
  • 第二引数 (parameters): メソッドに渡す引数を object 型の配列で指定します。引数がないメソッドの場合は null を渡します。

3. 戻り値の扱い

Invoke メソッドの戻り値は object 型です。呼び出したメソッドの戻り値が void の場合は null が返されます。値を利用する場合は、適切な型へのキャスト((int)result など)が必要です。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次