Search code examples
c#visual-studio-extensionsvsixvisual-studio-sdkobjectbrowser

Visual Studio SDK get type modifier information - is type abstract or internal?


I use the IVsObjectList2.GetCategoryField2 method to retrieve different information of a type.

Now I wonder how I can retrieve C# specific information like abstract or internal modifier of a type? The Object Browser can displays this informations.

enter image description here

Update 1:

I have made another attempt to get this information. Via the DynamicTypeService and the IVsHierarchy (of the project) I can get the TypeResolutionService. This can then return the Type I'm are looking for, and form the Type I get the infomrations (internal, abstract, etc.)

Unfortunately, this only works with .NET Framework projects. .NET Core projects don't work. The assumption is that .NET core projects cause problems when resolving, because the VS add-in (or Visual Studio SDK) run under .NET Framework.

var dte = Package.GetGlobalService(typeof(DTE)) as DTE2;
var serviceProvider = new ServiceProvider((Microsoft.VisualStudio.OLE.Interop.IServiceProvider)dte);

IVsSimpleObjectList2 objectList;
....
objectList.CountSourceItems(index, out var vsHierarchy, out var itemid, out var pcItems);

DynamicTypeService dynamicTypeService = (DynamicTypeService)serviceProvider.GetService(typeof(DynamicTypeService));
var typeResolutionService = dynamicTypeService.GetTypeResolutionService(hier);
var type = typeResolutionService.GetType("ObjectBuilder.ObjectBrowserTestTypes.AbstractTestClass");

More Infos here: Visual Studio Extension get all classes and interfaces metadata

I'm still looking for a solution. Does anyone have another idea?


Solution

  • At the end, I decided not to retrieve the information about the types via the Object-Browser or IVsObjectManager2. The reason is that I didn't get all the information I needed.

    For types in the currently loaded visual studio projects I'm using the ElementClass or CodeClass class.

    var service = Package.GetGlobalService(typeof(DTE)) as DTE2;
    Project project = service?.Solution?.Projects.Item(0);
    CodeType codeType = project.CodeModel.CodeTypeFromFullName("Full name of Type");
    
    if (codeType.Kind == vsCMElement.vsCMElementClass && codeType is CodeClass2 codeClass)
    {
        // get all the information form the code class
        var typeDescription = new TypeDescription();
        typeDescription.FullName = codeClass.FullName;
        typeDescription.ContainsGenericParameters = codeClass.IsGeneric;
        typeDescription.IsAbstract = codeClass.IsAbstract;
    }
    

    For types that are in a referenced assembly I'm using Mono.Cecil. The advantage of Mono.Cecil is, that it works with .NET Framework DLLs and .NET Core DLLs. The path of the referenced assembly can be gotten via the VS-SDK.

    var vsProject = project.Object as VSLangProj.VSProject;
    var assemblyPath = vsProject.References.Item(0).Path;
    
    ModuleDefinition module = Mono.Cecil.ModuleDefinition.ReadModule(assemblyPath);
    foreach (TypeDefinition type in module.Types)
    {
        var isAbstract = type.IsAbstract;
    }