Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Visual Studio Extension get all classes and interfaces metadata

I have successfully created the Visual Studio Extension project. It works nice and neat. I made some event for solutions.

The manuals in MSDN and the Internet are brief. And I cannot find an answer to my question: How can I retrieve all metadata related to the class and interfaces (namespaces, class names, base types, etc.) in the solution where this Extension Package is installed?

like image 509
alerya Avatar asked Sep 25 '15 21:09

alerya


2 Answers

You can use ITypeDiscoveryService to list all available types in project.

To do this, you should add Microsoft.VisualStudio.Shell.Design reference to project. This way you can use DynamicTypeService to get an instance of ITypeDiscoveryService.

Add this methods to your Package class:

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));
}

Then you can use GetAllTypes to get all types of active project:

List<Type> types= GetAllTypes();
like image 134
Reza Aghaei Avatar answered Nov 12 '22 17:11

Reza Aghaei


This code is about namespace, but you can easily transform it to take everything from 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;
    }
}
like image 41
alerya Avatar answered Nov 12 '22 15:11

alerya