如何使用Visual Studio扩展从当前解决方案中收集类型?

6
我创建了一个Visual Studio 2012套件(使用VS2012 SDK)。如果将此扩展安装在客户端的IDE环境中,则除其他功能外,它还应该具有从开发人员正在工作的当前打开解决方案中收集所有特定类型的功能。类似的功能嵌入在ASP.NET MVC应用程序项目的Visual Studio设计器中,其中开发人员实现模型/控制器类,构建项目,然后能够在脚手架UI(设计器下拉列表)中访问此类型。相应的功能也适用于WPF、WinForms Visual Designers等。
假设我的扩展必须收集当前解决方案中实现ISerializable接口的所有类型。步骤如下:开发人员创建特定类,重建包含的项目/解决方案,然后执行扩展UI提供的某些操作,从而涉及执行ISerializable类型收集。
我尝试使用反射来实现收集操作:
List<Type> types = AppDomain.CurrentDomain.GetAssemblies().ToList()
                  .SelectMany(s => s.GetTypes())
                  .Where(p => typeof(ISerializable).IsAssignableFrom(p) && !p.IsAbstract).ToList();

但是上述代码会导致抛出 System.Reflection.ReflectionTypeLoadException 异常:
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"}
(...)

如何正确实现从当前构建的解决方案中收集特定类型的操作?

我在相关主题通过DTE按类型名称查找ProjectItem中找到了一些示例代码,但这种迭代方法非常慢。在我的VS解决方案中,大约有60个项目,这段代码执行了十几秒钟,因此这不是绝对可接受的解决方案。我猜这是一个耗时的操作,但我相信有一种更快的方法来达到目标。Resharper及其类型收集模块在初始化期间可以更快地完成此任务。 - sgnsajgon
1
你在寻找解决方案的过程中有所收获吗? - JDandChips
2个回答

1

我曾尝试做类似的事情,不幸的是目前我找到的唯一解决方法是通过以下方式(我觉得有点混乱,但也许对于特定情况进行一些调整可能还可以)

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

这将给你所有类型,但你可以过滤掉任何你想要的。
参考此帖子: 如何在调用Assembly.GetTypes()时防止ReflectionTypeLoadException

1
我使用了CodeDOM模块来遍历VS插件内的解决方案元素,这与T4使用的相同。Roslyn将是一个很好的解决方案,但目前它还处于测试阶段。 我意识到使用标准反射机制无法从VS插件中收集类型信息,因为该解决方案类型未加载到插件CLR AppDomain中。 我知道Jetbrain的Resharper使用自己的解析和遍历模块,可能可以通过R#开发人员API进行访问。 - sgnsajgon

0

我不确定我是否正确理解了您的意思,但如果是这样,那将会是:

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

这段代码片段仅收集与其放置在同一程序集/项目中实现的 IDisposable 类型,即属于 Package 的程序集。但我需要收集在任何其他已安装并使用我的 Package 的开发人员的解决方案中实现的类型。这些类型不一定存在于我的 Package 源代码和程序集中。 - sgnsajgon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接