【问题标题】:Get reference to assembly from code generation tool从代码生成工具获取对程序集的引用
【发布时间】:2011-05-05 10:44:38
【问题描述】:

我目前正在实现一个自定义代码生成器,它将 XML 配置文件转换为 Visual Studio 项目中的 C# 类。我基本上遵循这篇博文中描述的方法:http://consultingblogs.emc.com/pauloreichert/archive/2005/05/21/1459.aspx

但是,代码生成器必须在使用生成器的程序集中查找所有可用类型及其属性。我想使用反射来做到这一点,但问题是我需要对要在其中查找类型的程序集的引用。

如何获得对代码生成器所在的 VS 项目程序集的引用?

【问题讨论】:

  • 听起来很像这个csd.codeplex.com它的开源,也许它的代码会对你有所帮助

标签: c# .net visual-studio reflection code-generation


【解决方案1】:

请注意,为了生成程序集,Visual Studio 需要编译工具输出的 C# 代码。因此,在您的代码生成器运行时,可能还没有组装(如果发生这种情况,则可以进行干净的构建)。

【讨论】:

  • 这完全有道理,但我认为你已经领先了一步......我不知道我实际上必须如何引用程序集。
  • 我的意思是(据我所知:-))您不能引用程序集,因为 VS 让您能够引用可能不会引用的东西没有任何意义存在。 :-)
  • 好的。但是没有其他方法可以在使用自定义工具生成代码的项目中查找可用类型吗?也许我更需要对 Visual Studio 项目对象或类似的引用?
  • 有两个问题 - 1) 如何访问 Visual Studio 可扩展性对象 对于项目,我不知道代码生成器有什么方法可以做到这一点; 2)如何在生成所有代码之前获取项目输出程序集中所有类型的信息,特别是在其中一些类型可能来自自定义代码生成器(例如您的工具)的情况下,我认为是不可能的,因为没有关于类型的信息,直到运行构建并编译所有代码。
  • 理论上,如果您可以访问项目中的项目列表,您可能能够枚举所有 C# 文件并即时编译它们以获取其中类型的元数据。但是,在构建运行 EF 代码生成器之前,您无法对将从 EF 建模语言生成的类型执行任何操作;并且无法保证构建将在您的代码生成器之前运行 EF 代码生成器。
【解决方案2】:

我找到了解决方案。实际上,可以从代码生成器中获取对 Visual Studio Project 对象的引用。

我在这里找到了获取项目参考的代码:http://subversion.assembla.com/svn/mistral-framework/trunk/src/VisualStudio/Mistral.VisualStudio.XmlClassGenerator/BaseCodeGeneratorWithSite.cs

下面的方法然后返回一个对程序集对象的引用,我们可以使用它通过反射来获取所有可用的类型等。

private static Assembly GetAssembly(Project project, string assemblyName)
{
    Microsoft.VisualStudio.OLE.Interop.IServiceProvider oleSP = 
        project.DTE as Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
    ServiceProvider sp = new ServiceProvider(oleSP);

    DynamicTypeService dts = 
        sp.GetService(typeof(DynamicTypeService)) as DynamicTypeService;

    Microsoft.VisualStudio.Shell.Interop.IVsSolution sln = 
        sp.GetService(typeof(SVsSolution)) as IVsSolution;

    Microsoft.VisualStudio.Shell.Interop.IVsHierarchy hier = null;
    sln.GetProjectOfUniqueName(project.UniqueName, out hier);

    ITypeResolutionService rs = dts.GetTypeResolutionService(hier);
    return rs.GetAssembly(new AssemblyName(assemblyName), true);
}

该方法仍然需要程序集名称,这对我来说很好,因为我可以从 XML 基础文件中读取它以进行生成。但是,我很确定您也可以在没有名称的情况下获得参考。 (当我开始工作时,我只是懒惰并停止调查;-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 2013-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多