假设有一个通用定义
MethodInfo
对象,即一个 MethodInfo
对象,使得 methodInfo.IsGenericMethodDefinition == true
:
MethodInfo methodInfo = somethingCool;
还说他们还有一个通用参数列表:
Type[] genericArguments = somethingElseAlsoCool;
我可以通过以下方式获取方法参数的类型:
Type[] types = (
from ParameterInfo parameter
in methodInfo.GetParameters()
select parameter.ParameterType
).ToArray();
现在,我可以用
methodInfo
填写 methodInfo.MakeGenericMethod
的通用参数:
MethodInfo invokableMethodInfo = methodInfo.MakeGenericMethod(genericArguments);
但是,
Type
数组又如何呢?我可以过早地增加这样的类型:
for (int i = 0; i < types.Length; i++)
types[i] = types[i].MakeGenericType(genericArguments);
但这没有意义。考虑以下方法:
void MyGenericMethod<TOne, TTwo, TThree>(IDictionary<TOne, TThree> Dictionary);
如果我执行前面提到的算法,那么类型将错误映射:
TOne => TKey //Fine, but only by coincidence.
TTwo => TValue //Incorrect. TValue should be TThree, not TTwo.
TThree => ? //What is this?
我被难住了。 如何在类型数组中定义未定义的泛型?
根据评论中的要求,这是一个测试用例:
using System.Reflection;
using static System.Console;
MethodInfo methodInfo = ((Delegate)MyTest<object, object>).Method.GetGenericMethodDefinition();
Type[] genericArguments = new Type[] { typeof(int), typeof(string) };
MethodInfo invokableMethodInfo = methodInfo.MakeGenericMethod(genericArguments);
WriteLine("----Method Invoke Result:");
invokableMethodInfo.Invoke(null, new object?[] { "hi" });
WriteLine("----End");
Type[] types = (
from ParameterInfo parameter
in methodInfo.GetParameters()
select parameter.ParameterType
).ToArray();
WriteLine();
WriteLine("----Undefined Generic Types:");
foreach (Type type in types)
WriteLine(type);
WriteLine("----End");
types = (
from ParameterInfo parameter
in invokableMethodInfo.GetParameters()
select parameter.ParameterType
).ToArray();
WriteLine();
WriteLine("----Defined Generic Types:");
foreach (Type type in types)
WriteLine(type);
WriteLine("----End");
ReadKey(true);
static void MyTest<TOne, TTwo>(TTwo Value)
{
WriteLine(typeof(TOne).ToString());
WriteLine(Value?.ToString());
}
它将输出:
----Method Invoke Result:
System.Int32
hi
----End
----Undefined Generic Types:
TTwo
----End
----Defined Generic Types:
System.String
----End
在我的代码中,我使用
methodInfo
来获取 Defined Generic Types
数组。我想改用 methodInfo
中的类型数组来获得相同的结果。
任何帮助将不胜感激!
不确定为什么您不能/不想使用
invokableMethodInfo
来获取“填充”参数类型。如果可以的话,你绝对应该这样做。
IsGenericMethodParameter
判断参数类型是否为类型参数,并使用 GenericParameterPosition
获取参数类型。 GenericParameterPosition
返回的索引可以直接用于访问您的genericArguments
数组。
这个想法基本上是,对于方法的每个参数,
genericArguments[GenericParameterPosition]
// perhaps the name of this could be better...
private static Type AssignConcreteTypesToGenericTypeParameter(Type parameter, Type[] arguments) {
if (parameter.IsGenericMethodParameter) {
return arguments[parameter.GenericParameterPosition];
}
if (parameter.IsGenericType) {
var typeArguments = parameter.GenericTypeArguments.Select(
x => AssignConcreteTypesToGenericTypeParameter(x, arguments)
).ToArray();
return parameter.GetGenericTypeDefinition().MakeGenericType(typeArguments);
}
return parameter;
}
使用示例:
MethodInfo methodInfo = ((Delegate)MyTest<object, object>).Method.GetGenericMethodDefinition();
Type[] arguments = new[] { typeof(string), typeof(int) };
var actualParameterTypes = methodInfo.GetParameters().Select(
x => AssignConcreteTypesToGenericTypeParameter(x.ParameterType, arguments)
);
foreach (var t in actualParameterTypes)
Console.WriteLine(t);