Visual Studio Extension获取所有类和接口元数据

本文关键字:接口 元数据 Studio Extension 获取 Visual | 更新日期: 2023-09-27 18:14:38

我已经成功创建了Visual Studio Extension项目。它工作得很好,很整洁。我做了一些事件来求解。

MSDN和Internet中的手册很简短。我找不到我问题的答案如何在安装此扩展包的解决方案中检索与类和接口(名称空间、类名、基类型等)相关的所有元数据?

Visual Studio Extension获取所有类和接口元数据

您可以使用ITypeDiscoveryService列出项目中所有可用的类型。

要做到这一点,您应该将Microsoft.VisualStudio.Shell.Design引用添加到项目中。通过这种方式,您可以使用DynamicTypeService来获得ITypeDiscoveryService的实例。

将这些方法添加到您的Package类中:

public List<Type> GetAllTypes()
{
    var trs = GetTypeDiscoveryService();
    var types = trs.GetTypes(typeof(object), true /*excludeGlobalTypes*/);
    var result = new List<Type>();
    foreach (Type type in types)
    {
        if (type.IsPublic)
        {
            if (!result.Contains(type))
                result.Add(type);
        }
    }
    return result;
}
private ITypeDiscoveryService GetTypeDiscoveryService()
{
    var dte = GetService<EnvDTE.DTE>();
    var typeService = GetService<DynamicTypeService>();
    var solution = GetService<IVsSolution>();
    IVsHierarchy hier;
    var projects = dte.ActiveSolutionProjects as Array;
    var currentProject = projects.GetValue(0) as Project;
    solution.GetProjectOfUniqueName(currentProject.UniqueName, out hier);
    return typeService.GetTypeDiscoveryService(hier);
}
private T GetService<T>()
{
    return (T)GetService(typeof(T));
}

然后你可以使用GetAllTypes来获取所有类型的活动项目:

List<Type> types= GetAllTypes();

这段代码是关于名称空间的,但您可以轻松地将其转换为从CodeModel中获取所有内容:

public class Metadata
{
    public List<Namespace> ExtractNamespaces()
    {
        var namespaces = new List<Namespace>();
        var service = (DTE)Package.GetGlobalService(typeof(SDTE));
        var projects = service.Solution.Projects;
        foreach (Project project in projects)
        {
            var projectItems = GetProjectItemsRecursively(project.ProjectItems);
            foreach (ProjectItem item in projectItems.Where(i => i.FileCodeModel != null))
            {
                foreach (CodeElement elem in item.FileCodeModel.CodeElements)
                {
                    namespaces.AddRange(GetNamespacesRecursive(elem).Select(n=>new Namespace(n)));
                }
            }
        }
        return namespaces.Distinct().OrderBy(n=>n.ToString()).ToList();
    }
    private static List<string> GetNamespacesRecursive(CodeElement elem)
    {
        var namespaces = new List<string>();
        if (IsNamespaceable(elem.Kind) && IsEmptyNamespace(elem))
        {
            namespaces.Add(string.Empty);
        }
        if (elem.Kind == vsCMElement.vsCMElementNamespace && !namespaces.Contains(elem.FullName))
        {
            namespaces.Add(elem.FullName);
            if (elem.Children != null)
            {
                foreach (CodeElement codeElement in elem.Children)
                {
                    var ns = GetNamespacesRecursive(codeElement);
                    if (ns.Count > 0)
                        namespaces.AddRange(ns);
                }
            }
        }
        return namespaces;
    }
    private static bool IsEmptyNamespace(CodeElement elem)
    {
        return elem.FullName.IndexOf('.') < 0;
    }
    private static bool IsNamespaceable(vsCMElement kind)
    {
        return (kind == vsCMElement.vsCMElementClass
                || kind == vsCMElement.vsCMElementEnum
                || kind == vsCMElement.vsCMElementInterface
                || kind == vsCMElement.vsCMElementStruct);
    }
    private static List<ProjectItem> GetProjectItemsRecursively(ProjectItems items)
    {
        var ret = new List<EnvDTE.ProjectItem>();
        if (items == null) return ret;
        foreach (ProjectItem item in items)
        {
            ret.Add(item);
            ret.AddRange(GetProjectItemsRecursively(item.ProjectItems));
        }
        return ret;
    }
}