C#反射:如何确定ParameterInfo是否是在父类上定义的泛型类型
本文关键字:父类 定义 泛型类型 是否是 反射 何确定 ParameterInfo | 更新日期: 2023-09-27 18:26:31
我有一个这样的方法签名:
public class Class1<TItem>
{
public void CopyTo(TItem[] items) { }
}
其中CCD_ 1是在父类上声明的。
当我使用反射来解析这个方法时:
// not returning TItem as generic in signature
string sig = method.FullName; // ClassLibrary1.Class1`1.CopyTo(TItem[])
if (method.ContainsGenericParameters) // true
{
Type[] genericArgs = method.GetGenericArguments(); // returns empty
foreach (Type genericArg in genericArgs)
{
loM.cGenericParameters += genericArg.Name + ",";
}
}
我需要弄清楚什么是泛型类型签名,这样我就可以查看XML文档(需要构建时髦的泛型类型查找签名)。我需要将方法签名映射到XML文档中的内容,该文档如下所示:
<member name="M:ClassLibrary1.Class1`1.CopyTo(`0[])">
我无法可靠地检测TItem[]是否是泛型的,也无法弄清楚如何(泛型地)获得泛型索引。
当我查看参数签名时,ParameterType.IsGenericType
和.GenericParameterPosition
都是false。ParameterType.ContainsGenericParameters
是真的,但它没有给我通用的原始类型签名(即签名所需的、通常在.FullName属性中看到的'0[]
)。
如果Generic定义在实际方法上(即SomeMethod<TItem>(TItem[] blah)
,在这一点上,我可以根据需要解析出参数。但当Generic参数在类型上定义时,我无法通过其泛型参数位置找到引用父泛型类型的正确签名。
我认为问题在于您查看的是方法的泛型参数,而不是方法的参数。您还必须区分数组和泛型类型。
if (method.ContainsGenericParameters)
{
foreach (var parameter in method.GetParameters())
{
if (parameter.ParameterType.IsArray)
{
var elementType = parameter.ParameterType.GetElementType();
var genericArgName = elementType.Name;
var genericParameterPosition = elementType.GenericParameterPosition;
}
else if (parameter.ParameterType.IsGenericType)
{
foreach (var genericArg in parameter.ParameterType.GetGenericArguments())
{
var genericArgName = genericArg.Name;
var genericParameterPosition = genericArg.GenericParameterPosition;
// If you need to differentiate between a generic arg that is declared
// in the method versus being declared in the class/interface/struct:
if (genericArg.DeclaringMethod == null)
{
// Declared in the class/interface/struct
}
else
{
// Declared in the method
}
}
}
}
}
当你在下面有类似Class2<>.Foo<>
的东西时,事情会变得有点奇怪——对于TItem
1循环的两次迭代,genericArg
变量的GenericParameterPosition
都是0
。检查DeclaringMethod
属性中的null值,以确定该位置所指的内容:方法或类/接口/结构。
public class Class2<TKey>
{
public void Foo<TValue>(IDictionary<TKey, TItem> items) { }
}