How to collect types from current solution using Visual Studio Extension?
Asked Answered
D

2

6

I have created Visual Studio 2012 Package (using VS2012 SDK). This Extension (if installed on the client's IDE environment) should has, among other things, a functionality of collecting all specific types from currently opened solution which developer is working on. A similar feature is embedded in Visual Studio Designer for ASP.NET MVC Application Project, where developer implements a Model/Controller class, build a project, and then is able to access this type in Scaffolding UI (Designer's dropdown list). The corresponding features are also available in WPF, WinForms Visual Designers, etc.

Let's say that my extension has to collect all types from current solution, which implement ISerializable interface. The steps are following: Developer creates specific class, rebuild containing project/solution, then do some action provided by extension UI, thus involves performing ISerializabletypes collecting.

I have tried to implement collecting operation using reflection:

List<Type> types = AppDomain.CurrentDomain.GetAssemblies().ToList()
                  .SelectMany(s => s.GetTypes())
                  .Where(p => typeof(ISerializable).IsAssignableFrom(p) && !p.IsAbstract).ToList();

But above code causes System.Reflection.ReflectionTypeLoadException exception to be thrown:

System.Reflection.ReflectionTypeLoadException was unhandled by user code
  HResult=-2146232830
  Message=Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
  Source=mscorlib
  StackTrace:
       at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
       at System.Reflection.RuntimeModule.GetTypes()
       at System.Reflection.Assembly.GetTypes()
(...)  
LoaderException: [System.Exception{System.TypeLoadException}]
{"Could not find Windows Runtime type   'Windows.System.ProcessorArchitecture'.":"Windows.System.ProcessorArchitecture"}
(...)

How can I properly implement operation of collecting specific types from currently built solution?

Dragoman answered 2/10, 2013 at 17:1 Comment(3)
Related topic: HowTo get all interfaces types from visual studio solution?Dragoman
I found some sample code in related topic Finding a ProjectItem by type name via DTE But this iterative approach is very, very slow. In my VS solution with about 60 project this code is executed a dozen or so seconds, therefore it is not absolutely acceptable solution. I guess it's time consuming operation, but I believe there is a faster way to reach a goal. Resharper and it's types collecting module does this job faster during initialization.Dragoman
Any joy with your search for a solution?Dumfries
D
1

I was trying to do a similar thing and unfortunately the only way around this I've found so far is by doing the following (which I feel is a bit messy, but maybe with some tweaking for a specific situation might be ok)

var assemblies = AppDomain.CurrentDomain.GetAssemblies();
IEnumerable<Type> types = assemblies.SelectMany(x => GetLoadableTypes(x));

...

public static IEnumerable<Type> GetLoadableTypes(Assembly assembly)
{
    try
    {
        return assembly.GetTypes();
    }
    catch (ReflectionTypeLoadException e)
    {
        return e.Types.Where(t => t != null);
    }
}

This would give you all types, but you can filter out whatever you wish.

Referenced this post: How to prevent ReflectionTypeLoadException when calling Assembly.GetTypes()

Dumfries answered 16/7, 2014 at 14:48 Comment(1)
I used CodeDOM module to traverse solution elements inside VS plugin, the same that is used by T4. The Roslyn will be great solution, but currently it's in beta stage. I realize that it's impossible to gather types info from VS plugin using standard reflection mechanism, because that solution types are not loaded into plugin CLR AppDomain. I know that Jetbrain's Resharper uses it's own parsing and traversing module, maybe accessible with the aid of R# developers API.Dragoman
P
0

I'm not sure if I understand you correctly, but if I am this will make it:

var assembly = Assembly.GetExecutingAssembly();
IEnumerable<Type> types = 
      assembly.DefinedTypes.Where(t => IsImplementingIDisposable(t))
                           .Select(t => t.UnderlyingSystemType);

........

private static bool IsImplementingIDisposable(TypeInfo t)
{
     return typeof(IDisposable).IsAssignableFrom(t.UnderlyingSystemType);
}
Penile answered 2/10, 2013 at 17:49 Comment(1)
This code snippet collects only IDisposable types which are implemented in the same assembly/project as it is placed in, in the assembly that is part of the Package. But I need to collect types that are implemented in any other solution of any developer who has installed and use my Package. Types, that not necessarily exists in my Package source code and assemblies.Dragoman

© 2022 - 2024 — McMap. All rights reserved.