CodeType获取通用参数

时间:2013-08-06 07:14:22

标签: c# generics envdte

我们正在使用Visual Studio CodeModel并且在获取CodeType的泛型参数时遇到一些问题。如何在不解析FullName的情况下获取它们?

How can I get the generic constraints from CodeInterface as a CodeType object?中暗示(虽然没有标记答案)没有其他办法,但是,这并不是真正可信的:

System.Func<Outer.Inner>

将无法定义:您无法知道您已解析的通用参数(Outer.Inner)是否指的是包含类Outer的命名空间Inner,或者它是否指的是具有内部类Outer的类Inner(是的,在这种情况下,它不是Outer+Inner

如果有人至少知道如何告诉FullName属性显示带有+符号的嵌套类,那么这也很棒。

2 个答案:

答案 0 :(得分:0)

我认为answer here非常明确。这不受DTE或DTE2的支持,将来不太可能得到支持。

目前唯一的方法是使用Roslyn,这对我们这些不想使用预发布软件的人来说是不可接受的。我还没有研究过哪种类型的依赖项(我的组件用户需要安装Roslyn吗?)。

可以使用正则表达式从FullName字符串中获取类型。但是,对于我们这些需要令牌(T)到具体类型(System.String)映射的现实世界中的人来说,这不是一种选择。

答案 1 :(得分:0)

我无法找到任何通用类型的方法,但如果您需要针对特定​​类型执行此操作,则在某些情况下可能会这样做。

例如,我有以下代码来检查类型是否是一个集合,如果是,则获取元素类型:

    private static bool IsCollectionType(CodeType type, out CodeType elementType)
    {
        // string implements IEnumerable<char>, but we don't want to treat it as a collection
        if (type.FullName == "System.String")
        {
            elementType = null;
            return false;
        }

        var enumerable = type.Bases.OfType<CodeInterface>().FirstOrDefault(i => i.FullName.StartsWith("System.Collections.Generic.IEnumerable<"));
        var method = enumerable?.Members.OfType<CodeFunction>().FirstOrDefault(m => m.Name == "GetEnumerator");
        var enumerator = method?.Type.CodeType;
        var current = enumerator?.Members.OfType<CodeProperty>().FirstOrDefault(m => m.Name == "Current");
        if (current != null)
        {
            elementType = current.Type.CodeType;
            return true;
        }

        elementType = null;
        return false;
    }

正如您所看到的,我并未直接查看泛型类型参数,而是查看IEnumerable<T>.GetEnumerator().Current的类型。当然,这需要具体了解您正在使用的类型。