どのように私は、リフレクションを使用して、特定の一般的な過負荷を見つけるには?
-
13-09-2019 - |
質問
私は(私の最初のテストケースに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;