获取泛型类型参数的数量

时间:2016-08-01 15:02:57

标签: c# .net generics reflection

有没有办法在未绑定的泛型类型中获取参数数量? 例如:

f(typeof(List<>))        => 1
f(typeof(Dictionary<,>)) => 2

UPD

我知道从Type.Name获取号码,但也许有办法从Type直接获取

3 个答案:

答案 0 :(得分:7)

您已经拥有通用类型定义。您需要做的就是获取泛型类型参数:

Type.GetGenericArguments().Length

修改

正如塞巴斯蒂安指出的那样,如果您习惯于处理C#,这可能会给您带来惊人的结果,因为C#隐藏了“继承”的泛型类型参数。例如:

void Main()
{
  typeof(A<>.Nested<>).GetGenericArguments().Dump();
}

public class A<T>
{
  public class Nested<V>
  {

  }
}

会给你{ typeof(T), typeof(V) }。这就是.NET类的实际情况 - 这就是你需要如何引用它,如何通过反射创建它。

这只有在你特别试图用C#编译器对编译时未知的类做一些事情时才有意义;这可能意味着您正在尝试生成C#代码。似乎没有任何支持的方式来获得C#安全的行为 - 你只需要使用真正的代码生成器而不是将字符串拼接在一起:)

答案 1 :(得分:1)

Luaan's answer不适用于嵌套类型。

例如,如果您有OuterClass<,>.InnerClass<>,则会发出1个参数 - 但.NET实际上会报告3

我找到解决此问题的唯一方法是解析泛型类型定义的名称,如下所示:

public static int GetGenericParameterCount(Type type)
{
    if (!type.IsGenericType)
    {
        return 0;
    }

    var genericTypeDefName = type.GetGenericTypeDefinition().Name;
    int tickIndex = genericTypeDefName.LastIndexOf('`');
    if (tickIndex == -1)
    {
        // This will happen for nested types like "OuterClass<int>.InnerClass".
        return 0;
    }

    return int.Parse(genericTypeDefName.Substring(tickIndex + 1), NumberStyles.None);
}

答案 2 :(得分:1)

计算通用参数总数

只需查询t.GetGenericArguments().Length即可找到某种类型t的通用参数(或参数)的总数:

static int GenericParameterCount(this Type t)
    => t.IsGenericType ? t.GetGenericArguments().Length
                       : 0;

仅限嵌套类型:计算“本地”通用参数的数量(不包括从外部类型继承的参数)

对嵌套类型执行上述操作可能会产生最初令人惊讶的结果。例如,类型Outer<T>.Inner有1个通用参数,类型Outer<T>.Inner<U>有2.只要您将这些嵌套类型视为Inner或{{1},这似乎是不正确的(即它们在源代码中声明的方式)。

(出于同样的原因,您可能最初会惊讶地发现Inner<U>,即使查询的类型typeof(Outer<T>.Inner).IsGenericType == true似乎不是通用的。)

如果您确实只想计算“本地”泛型类型参数并排除从其外部类型继承的参数,则可以简单地减去外部类型(Inner)通用参数总数:

type.DeclaringType