Exponer listas de símbolos proporcionados por la biblioteca al administrador de objetos

Las herramientas de exploración de símbolos, la vista de clases, el examinador de objetos, el explorador de llamadas y los resultados de buscar símbolos, pasan solicitudes de nuevos datos al administrador de objetos de Visual Studio. El administrador de objetos busca las bibliotecas adecuadas y solicita nuevas listas de símbolos. Las bibliotecas responden proporcionando datos solicitados al administrador de objetos de Visual Studio a través de la IVsSimpleObjectList2 interfaz . El administrador de objetos de Visual Studio llama a los métodos de la IVsSimpleObjectList2 interfaz para obtener los datos y los usa para rellenar o actualizar las vistas de las herramientas de exploración de símbolos.

Una biblioteca puede obtener solicitudes de datos cuando se invoca la herramienta, el nodo se expande o se actualiza la vista. Cuando se invoca una herramienta de exploración de símbolos por primera vez, el administrador de objetos solicita a la biblioteca que proporcione la lista de nivel superior. Cuando el usuario expande un nodo de lista, la biblioteca proporciona una lista de elementos secundarios de ese nodo. Cada consulta del administrador de objetos contiene un índice del elemento de interés. Para mostrar una nueva lista, el administrador de objetos debe determinar cuántos elementos están en la lista, el tipo de los elementos, sus nombres, accesibilidad y otras propiedades.

Nota:

Los siguientes ejemplos de código administrado muestran cómo proporcionar listas de símbolos mediante la implementación de la IVsSimpleObjectList2 interfaz . El administrador de objetos llama a los métodos de esta interfaz y usa los datos obtenidos para rellenar o actualizar las herramientas de exploración de símbolos.

Para la implementación del proveedor de símbolos de código nativo, use la IVsObjectList2 interfaz .

Para proporcionar listas de símbolos al administrador de objetos

  1. Obtenga el número de elementos de la lista de símbolos mediante la implementación del GetItemCount método . En el ejemplo siguiente se muestra cómo el administrador de objetos obtiene la información sobre el número de elementos de la lista.

    protected System.Collections.Generic.SortedList<string, Method> m_Methods = new System.Collections.Generic.SortedList<string, Method>();
    
    public int GetItemCount(out uint pCount)
    {
        pCount = (uint)m_Methods.Count;
        return Microsoft.VisualStudio.VSConstants.S_OK;
    }
    
    
  2. Obtenga información sobre las categorías y los atributos de un elemento de lista determinado mediante la implementación del GetCategoryField2 método . Las categorías de elementos se especifican en la LIB_CATEGORY enumeración . En el ejemplo siguiente se muestra cómo el administrador de objetos obtiene los atributos de los elementos de una categoría determinada.

    public int GetCategoryField2(uint index, int Category, out uint pfCatField)
    {
        pfCatField = 0;
    
        switch ((LIB_CATEGORY)Category)
        {
            case LIB_CATEGORY.LC_MEMBERTYPE:
                pfCatField = (uint)_LIBCAT_MEMBERTYPE.LCMT_METHOD;
                break;
    
            case LIB_CATEGORY.LC_MEMBERACCESS:
                {
                    Method method = m_Methods.Values[(int)index];
    
                    if (method.IsPublic)
                    {
                        pfCatField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PUBLIC;
                    }
                    else if (method.IsPrivate)
                    {
                        pfCatField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PRIVATE;
                    }
                    else if (method.IsFamily)
                    {
                        pfCatField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PROTECTED;
                    }
                    else if (method.IsFamilyOrAssembly)
                    {
                        pfCatField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PROTECTED |
                                     (uint)_LIBCAT_MEMBERACCESS.LCMA_PACKAGE;
                    }
                    else
                    {
                        // Show everything else as internal.
                        pfCatField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PACKAGE;
                    }
                }
                break;
    
            case LIB_CATEGORY.LC_VISIBILITY:
                pfCatField = (uint)_LIBCAT_VISIBILITY.LCV_VISIBLE;
                break;
    
            case LIB_CATEGORY.LC_LISTTYPE:
                pfCatField = (uint)_LIB_LISTTYPE.LLT_MEMBERS;
                break;
    
            default:
                return Microsoft.VisualStudio.VSConstants.S_FALSE;
        }
        return Microsoft.VisualStudio.VSConstants.S_OK;
    }
    
    
  3. Obtenga la representación de texto de un elemento de lista determinado mediante la implementación del GetTextWithOwnership método . En el ejemplo siguiente se muestra cómo obtener un nombre completo de un elemento determinado.

    public int GetTextWithOwnership([System.Runtime.InteropServices.ComAliasNameAttribute("Microsoft.VisualStudio.OLE.Interop.ULONG")] uint index, [System.Runtime.InteropServices.ComAliasNameAttribute("Microsoft.VisualStudio.Shell.Interop.VSTREETEXTOPTIONS")] Microsoft.VisualStudio.Shell.Interop.VSTREETEXTOPTIONS tto, [System.Runtime.InteropServices.ComAliasNameAttribute("Microsoft.VisualStudio.OLE.Interop.WCHAR")] out string ppszText)
    {
        ppszText = m_Methods.Values[(int)index].FullName;
        return Microsoft.VisualStudio.VSConstants.S_OK;
    }
    
    
  4. Obtenga la información del icono de un elemento de lista determinado mediante la implementación del GetDisplayData método . El icono representa el tipo (clase, método, etc.) y accesibilidad (privado, público, etc.) de un elemento de lista. En el ejemplo siguiente se muestra cómo obtener la información del icono en función de los atributos de un elemento determinado.

    public virtual int GetDisplayData(uint index, Microsoft.VisualStudio.Shell.Interop.VSTREEDISPLAYDATA[] pData)
    {
        if (pData == null)
        {
            return Microsoft.VisualStudio.VSConstants.E_INVALIDARG;
        }
    
        Method method = m_Methods.Values[(int)index];
    
        int iImage = 12 * 6;    // See env\inc\OMGlyphs.h.
    
        const int OM_GLYPH_ACC_PUBLIC = 0;
        const int OM_GLYPH_ACC_INTERNAL = 1;
        const int OM_GLYPH_ACC_PROTECTED = 3;
        const int OM_GLYPH_ACC_PRIVATE = 4;
    
        if (method.IsPublic)
        {
            iImage += OM_GLYPH_ACC_PUBLIC;
        }
        else if (method.IsPrivate)
        {
            iImage += OM_GLYPH_ACC_PRIVATE;
        }
        else if (method.IsFamily)
        {
            iImage += OM_GLYPH_ACC_PROTECTED;
        }
        else if (method.IsFamilyOrAssembly)
        {
            iImage += OM_GLYPH_ACC_PROTECTED;
        }
        else
        {
            iImage += OM_GLYPH_ACC_INTERNAL;
        }
    
        pData[0].Image = (ushort)iImage;
        pData[0].SelectedImage = (ushort)iImage;
    
        return Microsoft.VisualStudio.VSConstants.S_OK;
    }
    
    
  5. Obtenga la información sobre si un elemento de lista determinado se puede expandir mediante la implementación del GetExpandable3 método . En el ejemplo siguiente se muestra cómo obtener la información sobre si se puede expandir un elemento determinado.

    public int GetExpandable(uint index, out int pfExpandable)
    {
        pfExpandable = Microsoft.VisualStudio.VSIP.Samples.CallBrowser.Constants.TRUE;
        return Microsoft.VisualStudio.VSConstants.S_OK;
    }
    
    public int GetExpandable3(uint index, uint ListTypeExcluded, out int pfExpandable)
    {
        return GetExpandable(index, out pfExpandable);
    }
    
    
  6. Para obtener una lista secundaria de símbolos de un elemento de lista determinado, implemente el GetList2 método . En el ejemplo siguiente se muestra cómo obtener una lista secundaria de símbolos de un elemento determinado para gráficos Call o Callers .

    // Call graph list.
    public class CallsList :
        ResultsList,
        Microsoft.VisualStudio.Shell.Interop.IVsSimpleObjectList2
    {
        public CallsList(Library library) :
            base(library)
        {
        }
    
        public int GetList2(uint index, uint ListType, uint flags, Microsoft.VisualStudio.Shell.Interop.VSOBSEARCHCRITERIA2[] pobSrch, out Microsoft.VisualStudio.Shell.Interop.IVsSimpleObjectList2 ppList)
        {
            return base.GetCallsList(index, out ppList);
        }
    }
    
    // Callers graph list.
    public class CallersList :
        ResultsList,
        Microsoft.VisualStudio.Shell.Interop.IVsSimpleObjectList2
    {
        public CallersList(Library library) :
            base(library)
        {
        }
    
        public int GetList2(uint index, uint ListType, uint flags, Microsoft.VisualStudio.Shell.Interop.VSOBSEARCHCRITERIA2[] pobSrch, out Microsoft.VisualStudio.Shell.Interop.IVsSimpleObjectList2 ppList)
        {
            return base.GetCallersList(index, out ppList);
        }
    }
    
    // Call graph list.
    public int GetCallsList(uint index, out Microsoft.VisualStudio.Shell.Interop.IVsSimpleObjectList2 ppList)
    {
        ppList = null;
        ResultsList callsList = new CallsList(m_Library);
    
        Method method = m_Methods.Values[(int)index];
        string strMethod = method.m_strPrototype;
    
        System.Collections.Generic.List<CallInstance> Calls = m_Library.CallGraph.GetCallGraph(method);
    
        for (int i = 0; i < Calls.Count; i++)
        {
            Method caller = Calls[i].m_Target;
            callsList.AddMethod(caller);
        }
    
        ppList = (Microsoft.VisualStudio.Shell.Interop.IVsSimpleObjectList2)(callsList);
        return Microsoft.VisualStudio.VSConstants.S_OK;
    }
    
    // Callers graph list.
    public int GetCallersList(uint index, out Microsoft.VisualStudio.Shell.Interop.IVsSimpleObjectList2 ppList)
    {
        ppList = null;
        ResultsList callersList = new CallersList(m_Library);
    
        Method method = m_Methods.Values[(int)index];
        string strMethod = method.m_strPrototype;
    
        System.Collections.Generic.List<CallInstance> Callers = m_Library.CallGraph.GetCallersGraph(method);
    
        for (int i = 0; i < Callers.Count; i++)
        {
            Method caller = Callers[i].m_Source;
            callersList.AddMethod(caller);
        }
    
        ppList = (Microsoft.VisualStudio.Shell.Interop.IVsSimpleObjectList2)(callersList);
        return Microsoft.VisualStudio.VSConstants.S_OK;
    }
    
    // Get a child list of symbols for a given list item.
    public int GetList2(uint index, uint ListType, uint flags, Microsoft.VisualStudio.Shell.Interop.VSOBSEARCHCRITERIA2[] pobSrch, out Microsoft.VisualStudio.Shell.Interop.IVsSimpleObjectList2 ppList)
    {
        ppList = null;
    
        Method method = m_Methods.Values[(int)index];
        string strMethod = method.m_strPrototype;
    
        // Determine if the list belongs to Call or Callers graphs.
        if ((uint)(m_nFlags & (uint)Microsoft.VisualStudio.Shell.Interop._VSOBSEARCHOPTIONS2.VSOBSO_CALLSFROM) > 0)
        {
            // Build the list for the Call graph.
            return base.GetCallsList(index, out ppList);
        }
        else if ((uint)(m_nFlags & (uint)Microsoft.VisualStudio.Shell.Interop._VSOBSEARCHOPTIONS2.VSOBSO_CALLSTO) > 0)
        {
            // Build the list for the Callers graph.
            return base.GetCallersList(index, out ppList);
        }
    
        return Microsoft.VisualStudio.VSConstants.E_FAIL;
    }