実行時にのみ判明する型引数を持つジェネリックメソッドの呼び出し [重複] 質問する

実行時にのみ判明する型引数を持つジェネリックメソッドの呼び出し [重複] 質問する

編集:

もちろん、実際のコードはこれとまったく同じではありません。自分が何をしたいのかをより明確にするために、半疑似コードを書いてみました。

むしろ物事を台無しにしてしまったようです。

つまり、私が実際にやりたいことはこれです:

Method<Interface1>();
Method<Interface2>();
Method<Interface3>();
...

まあ...リフレクションを使ってループにできるかもしれないと思ったのですが、問題はどうやってそれをするかです。とてもリフレクションに関する知識が浅い。そのため、コード例があると助かります。

シナリオは次のようになります。

public void Method<T>() where T : class
{}
public void AnotherMethod()
{
    Assembly assembly = Assembly.GetExecutingAssembly();

    var interfaces = from i in assembly.GetTypes()
    where i.Namespace == "MyNamespace.Interface" // only interfaces stored here
    select i;

    foreach(var i in interfaces)
    {
        Method<i>(); // Get compile error here!
    }




元の投稿:

こんにちは!

名前空間内のすべてのインターフェースをループし、次のように汎用メソッドに引数として送信しようとしています。

public void Method<T>() where T : class
{}
public void AnotherMethod()
{
    Assembly assembly = Assembly.GetExecutingAssembly();

    var interfaces = from i in assembly.GetTypes()
    where i.Namespace == "MyNamespace.Interface" // only interfaces stored here
    select i;

    foreach(var interface in interfaces)
    {
        Method<interface>(); // Get compile error here!
    }
}

「型名が必要ですが、ローカル変数名が見つかりました」というエラーが表示されます。

...
    foreach(var interface in interfaces)
    {
        Method<interface.MakeGenericType()>(); // Still get compile error here!
    }
}

「演算子 '<' をタイプ 'method group' および 'System.Type' のオペランドに適用できません」というメッセージが表示されます。この問題を回避する方法について何かアイデアはありますか?

ベストアンサー1

編集: さて、短いですが完全なプログラムの時間です。基本的な答えは前と同じです:

  • Type.GetMethod で「open」ジェネリックメソッドを見つける
  • MakeGenericMethodを使用して汎用化します
  • Invokeで呼び出す

ここにサンプル コードがあります。クエリ式をドット表記に変更したことに注意してください。基本的に where 句しかない場合は、クエリ式を使用する意味がありません。

using System;
using System.Linq;
using System.Reflection;

namespace Interfaces
{
    interface IFoo {}
    interface IBar {}
    interface IBaz {}
}

public class Test
{
    public static void CallMe<T>()
    {
        Console.WriteLine("typeof(T): {0}", typeof(T));
    }

    static void Main()
    {
        MethodInfo method = typeof(Test).GetMethod("CallMe");

        var types = typeof(Test).Assembly.GetTypes()
                                .Where(t => t.Namespace == "Interfaces");

        foreach (Type type in types)
        {
            MethodInfo genericMethod = method.MakeGenericMethod(type);
            genericMethod.Invoke(null, null); // No target, no arguments
        }
    }
}

元の回答

まず、変数を「インターフェース」と呼ぶことの明らかな問題は脇に置いておきましょう。

リフレクションで呼び出す必要があります。ジェネリックのポイントは、より多くの型チェックを行うことです。コンパイルコンパイル時には型が何であるか分からないため、ジェネリックを使用する必要があります。

ジェネリック メソッドを取得し、それに対して MakeGenericMethod を呼び出して、それを呼び出します。

インターフェース型自体はジェネリックですか? MakeGenericType を呼び出していますが、型引数を渡していないので質問します... 呼び出そうとしているのですか?

Method<MyNamespace.Interface<string>>(); // (Or whatever instead of string)

または

Method<MyNamespace.Interface>();

後者の場合、MakeGenericType ではなく MakeGenericMethod を呼び出すだけで済みます。

おすすめ記事