确定一个字段是否使用了通用参数

3

我感到困惑,无法理解这个问题,希望有人能指点一下我。

我有一个如下的类:

public class Foo<T>
{
    public List<T> Data;
}

现在我正在编写代码以反映这个类,并想出一种确定字段Data正在使用泛型参数的方法。
我的初始方法是继续向下走尽可能多的层次,一旦遇到IsGenericParameter字段设置为true,我会将类型名称替换为“Generic Argument”字符串,但是我似乎无法使它按照我想要的方式工作。
我已经搜索过了,但是目前我找到的每个解决方案似乎都指向了死胡同。

1
你最初拥有的 System.Type 实例是什么?是 typeof(Foo<>) 还是类似于 typeof(Foo<SomeType>) 的东西? - Sergey Kalinichenko
嗨 @dasblinkenlight,实例是Foo<SomeType>。 - Alex
只是补充一下,然后我遍历这些字段,所以当使用Foo<SomeType>并且到达Data字段时,在列表之后,字符串本身没有将'IsGenericParameter'设置为true。 - Alex
只是为了确认,您想知道Data是否使用了通用类型? - romain-aga
2
IsGenericType 是你要找的吗?例如:typeof(Foo<int>).GetField("Data").FieldType.IsGenericType - D Stanley
2个回答

3

你需要使用IsGenericType,而不是IsGenericParameter

bool isGeneric = typeof(Foo<int>).GetField("Data").FieldType.IsGenericType;

如果你想知道 List 的参数是否是泛型的,那么你需要再往下看一层:

bool isGeneric = typeof(Foo<>).GetField("Data")
                                 .FieldType
                                 .GetGenericArguments()[0] // only generic argument to List<T>
                                 .IsGenericParameter;

如果Data字段是一个带有Dictionary<string, T>Dictionary,那么我如何确定使用了哪种类型的泛型参数?
在该类型上调用GetGenericArguments,并查看结果数组中的每个类型。
public class Foo<T>
{
    public Dictionary<string, T> Bar;
}

Type[] types = typeof(Foo<>).GetField("Bar").FieldType.GetGenericArguments();

Console.WriteLine("{0}\n{1}",
    types[0].IsGenericParameter,  // false, type is string
    types[1].IsGenericParameter   // true,  type is T
);

基本上,IsGenericParameter 用于查看类型的通用参数,以查看它是否是通用的或者是否已指定了类型。

1
好的,这看起来很合理,但是如果Data字段是一个带有Dictionary<string,T>的字典……我该如何确定使用泛型参数的类型? - Alex
谢谢 - 这也帮助我找到了正确的地方,但是上面的用户略微快了一点,所以我认为把那个标记为正确答案是公平的 :) - Alex

1
这里是区分依赖于类类型参数的通用类型和不依赖于类类型参数的通用类型的方法。考虑以下示例:
class Foo<T> {
    public List<T> field1;   // You want this field
    public List<int> field2; // not this field
}

首先获取通用类型定义,并提取其类型参数:

var g = typeof(Foo<string>).GetGenericTypeDefinition();
var a = g.GetGenericArguments();

这将为您提供一个数组,其中包含代表通用类型参数 T 的单个类型。现在,您可以遍历所有字段,并在字段类型的通用类型参数中搜索该类型,例如:
foreach (var f in g.GetFields()) {
    var ft = f.FieldType;
    if (!ft.IsGenericType) continue;
    var da = ft.GetGenericArguments();
    if (da.Any(xt => a.Contains(xt))) {
        Console.WriteLine("Field {0} uses generic type parameter", f.Name);
    } else {
        Console.WriteLine("Field {0} does not use generic type parameter", f.Name);
    }
}

这段代码生成以下输出
Field field1 uses generic type parameter
Field field2 does not use generic type parameter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接