gpt4 book ai didi

Replace Generic Types In `System.Type[]` With Types(将`System.Type[]`中的泛型类型替换为类型)

转载 作者:bug小助手 更新时间:2023-10-28 20:25:36 30 4
gpt4 key购买 nike



Say one has a generic definition MethodInfo object, that is, a MethodInfo object such that methodInfo.IsGenericMethodDefinition == true:

假设有一个泛型定义的方法信息对象,即一个方法信息对象,这样的方法Info.IsGenericMethodDefinition==TRUE:


MethodInfo methodInfo = somethingCool;

Say also that they also have a list of generic arguments:

也可以说它们也有一个泛型参数列表:


Type[] genericArguments = somethingElseAlsoCool;

I can get the types of the parameters of the method with:

我可以使用以下命令获取该方法的参数类型:


Type[] types = (
from ParameterInfo parameter
in methodInfo.GetParameters()
select parameter.ParameterType
).ToArray();

Now, I can fill in the generic arguments to methodInfo with methodInfo.MakeGenericMethod:

现在,我可以使用方法Info.MakeGenericMethod来填充方法信息的泛型参数:


MethodInfo invokableMethodInfo = methodInfo.MakeGenericMethod(genericArguments);

However, what about the array of Types? I can just prematurely increment though the types as such:

但是,类型数组又如何呢?我可以通过以下类型过早地递增:


for (int i = 0; i < types.Length; i++)
types[i] = types[i].MakeGenericType(genericArguments);

But this wouldn't make sense. Consider the following method:

但这说不通。请考虑以下方法:


void MyGenericMethod<TOne, TTwo, TThree>(IDictionary<TOne, TThree> Dictionary);

If I did the previously mentioned algorithm, then the types would map incorrectly:

如果我执行前面提到的算法,则类型将不正确地映射:


TOne   => TKey   //Fine, but only by coincidence.
TTwo => TValue //Incorrect. TValue should be TThree, not TTwo.
TThree => ? //What is this?

I'm stumped. How can I define the undefined generics in my array of types?

我被难住了。如何在类型数组中定义未定义的泛型?


As requested by those in the comments, here is a test case:

应评论中的那些人的要求,下面是一个测试案例:


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());
}

It will output:

它将输出:


----Method Invoke Result:
System.Int32
hi
----End

----Undefined Generic Types:
TTwo
----End

----Defined Generic Types:
System.String
----End

In my code, I use the invokableMethodInfo (calculated from the original methodInfo) to get the Defined Generic Types array. I would like to instead use the array of types from the methodInfo to get the same result.

在我的代码中,我使用invokableMethodInfo(根据原始方法信息计算)来获取已定义的泛型类型数组。我想改用方法信息中的类型数组来获得相同的结果。


Any help would be greatly appreciated!

如有任何帮助,将不胜感激!


更多回答

How about getting the types after you do MakeGenericMethod?

在你做了MakeGenericMethod之后获取类型怎么样?

Can you show a concrete example of methodInfo, genericArguments, and the value of types that you want to get as output?

您能展示一个方法信息、GenericArguments和您想要作为输出获得的类型的值的具体示例吗?

@Sweeper 1. My question assumed that the methodInfo object was disposed of after creating the array of Types. 2. I'll see what I can do.

@Sweeper 1.我的问题假定方法Info对象在创建类型数组之后被释放。2.我看看我能做些什么。

@Sweeper Edited one in just now.

@Sweeper刚刚在里面编辑了一个。

Thank you. That is much clearer. Is there a typo in the last paragraph? Did you mean "I use the invokableMethodInfo to get the Defined Generic Types array"?

谢谢。这一点要清楚得多。最后一段有没有打字错误?您的意思是“我使用invokableMethodInfo来获取已定义的泛型类型数组”?

优秀答案推荐

Not sure why you can't/don't want to use invokableMethodInfo to get the "filled in" parameter types. You should definitely do that if you can.

不确定为什么不能/不想使用invokableMethodInfo来获取“填充的”参数类型。如果可以的话,你绝对应该这么做。


Otherwise, you would have to do the "type replacing" yourself. You can find whether a parameter type is a type parameter by using IsGenericMethodParameter, and get which type parameter it is by using GenericParameterPosition. The index returned by GenericParameterPosition can be directly used to access your genericArguments array.

否则,您将不得不自己进行“类型替换”。您可以通过使用IsGenericMethodParameter来确定参数类型是否为类型参数,并通过使用Generic参数位置来获取它是哪种类型的参数。Generic参数位置返回的索引可直接用于访问GenericArguments数组。


The idea is basically, for each parameter of the method,

这个想法基本上是,对于方法的每个参数,



  • if it is a type parameter, replace it with genericArguments[GenericParameterPosition]

  • if it is a generic type, recursively replace each of its type arguments with this algorithm

  • if it is an array type, recursively replace the array element type

  • if it is an byref type, recursively replace the byref element type

  • if it is an pointer type, recursively replace the pointer element type

  • otherwise, don't change it


// 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)
return
parameter
.GetGenericTypeDefinition()
.MakeGenericType((
from Type x in ParameterType.GenericTypeArguments
select _AssignGenericsToParameterType(x, parameter))
.ToArray());
if (parameter.IsArray)
return
_AssignGenericsToParameterType(parameter.GetElementType()!, parameter)
.MakeArrayType(parameter.GetArrayRank());
if (parameter.IsByRef)
return
_AssignGenericsToParameterType(parameter.GetElementType()!, parameter)
.MakeByRefType();
if (parameter.IsPointer)
return
_AssignGenericsToParameterType(parameter.GetElementType()!, parameter)
.MakePointerType();
return parameter;
}

Example usage:

用法示例:


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);

Bear in mind, that there may be some edge cases that this doesn't handle. The .NET system is rather complicated. I've tried to handle all I could think of (arrays, references, pointers, et cetera), but a few might have slipped through. At any rate, such edge cases will probably be easy to correct when encountered.

请记住,这可能不能处理某些边缘情况。.NET系统相当复杂。我试着处理我能想到的所有东西(数组、引用、指针等),但可能有几个漏掉了。无论如何,当遇到这种边缘情况时,可能很容易纠正。


Happy coding!

编码快乐!


更多回答

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com