どのように私は、リフレクションを使用して、特定の一般的な過負荷を見つけるには?

StackOverflow https://stackoverflow.com/questions/1465715

質問

私は(私の最初のテストケースにExpression)特定のジェネリックオーバーロードされたメソッドを呼び出しますEnumerable.Averageを作成しようとしています。特定のタイプのバインディングが実行時まで知られていないが、私は(Reflectionが解析されたテキストから作成されている)。見つけて、正しいジェネリックメソッドを作成するためにExpressionを使用する必要があるので、

私は、この特定のオーバーロードを見つけたいその実行時に知っているので、もします:

public static double Average<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector)

どのように私はリフレクションを使用して、特定のMethodInfoを解決するのですか?

これまでのところ、私は次の選択ステートメントを持っています:

MethodInfo GetMethod(Type argType, Type returnType)
{
    var methods = from method in typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static)
      where method.Name == "Average" &&
      method.ContainsGenericParameters &&                              
      method.GetParameters().Length == 2 &&
      // and some condition where method.GetParameters()[1] is a Func that returns type argType
      method.ReturnType == returnType
      select method;

      Debug.Assert(methods.Count() == 1);
      return methods.FirstOrDefault();
}

上記の3つのオーバーロードにそれを絞り込むが、私はFunc<TSource, int> argType == typeof(int)を取り、特定の過負荷を反映して検索する。

私は困惑していますし、任意のヘルプは高く評価されます。

役に立ちましたか?

解決

<ストライキ>あなたは MethodInfo.MakeGenericMethodを使用する必要があります

編集:OK、私は問題を誤解していた...この方法は、あなたが欲しいものを行う必要があります:

MethodInfo GetMethod(Type argType, Type returnType)
{
    var enumerableType = typeof(IEnumerable<>).MakeGenericType(new Type[] { argType });
    Console.WriteLine(enumerableType);
    var methods = from method in typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static)
      let parameters = method.GetParameters()
      let genParams = method.GetGenericArguments()
      where method.Name == "Average" &&
      method.ContainsGenericParameters &&                              
      parameters.Length == 2 &&
      parameters[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>) &&
      parameters[1].ParameterType.GetGenericArguments()[1] == argType &&
      method.ReturnType == returnType
      select method;

      return methods.FirstOrDefault();
}

他のヒント

あなたが直接実行するのではなく、式を構築しているので、あなたがMETHODINFOのステップをスキップすることができますし、METHODINFOではなく、メソッド名を受け取りExpression.Callのオーバーロードを使用してMethodCallExpressionに直行ます。

var call = Expression.Call(typeof(Enumerable),
             "Average",
            new Type[] { typeof(MyTSource) },
            enumerableParameter, lambdaParameter
                );

ここでそれを行う方法は次のとおりです。

static MethodInfo GetMethod(Type argType, Type returnType)
{
    var methods = from m in typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                  where m.ContainsGenericParameters
                  && m.Name == "Average"
                  && m.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>)
                  && m.GetParameters()[1].ParameterType.GetGenericArguments()[1] == returnType
                  select m;
    return methods.First();
}

リンクのヒントをありがとう@Joren。その一例は、引数の数に基づいていますが、それは正しい方向に私を得差別ます。

作品の選択がある。

var methods = from method in typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static)
where method.Name == Name &&
method.ContainsGenericParameters &&                                                    
method.ReturnType == returnType &&
method.GetParameters().Length == 2 &&
method.GetParameters()[1].ParameterType.GetGenericArguments().Count() == 2 &&
method.GetParameters()[1].ParameterType.GetGenericArguments()[1] == argType
select method;
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top