2

我有一个带有两个输出 dll 的解决方案(实际上更多,但让我们保持简单)。项目“特​​殊”引用项目“普通”。

我尝试编写一个代码生成器来解析“特殊”中的一些文件并将生成的存根代码放入项目“通用”中。为了处理这个循环引用,我需要处理无法编译的代码。所以我正在使用罗斯林。

生成器需要根据继承信息替换一些类型,所以我需要构造一个编译单元来访问语义模型。此外,我需要根据类型的来源替换一些东西(无论它们是在“特殊”还是“通用”中定义的。或者更准确地说:基于全局程序集属性)。

生成器必须能够作为 MSBuild 任务运行。

我尝试了两种方法来设置我的环境,但我都坚持:

  1. 我试图在生成器中加载我的解决方案。由于“无法将透明代理转换为类型 'Roslyn.Utilities.SerializableDataStorage'”,此操作失败。然后我尝试从头开始创建解决方案,添加 IProjects 和 IDocuments 并且我已经按照此答案中的建议尝试了 LoadProjectFromCommandLineArguments ,但似乎没有什么对我有用,从 MSBuild 运行时我得到了同样的异常(通过安慰)。

    任何人都知道如何处理 SerializableDataStorage 异常?

  2. 我试图创建一个编译并添加我所有的 cs 源。但是现在我找不到一种方法来知道我的符号是来自“特殊”还是“普通”程序集。

    我可以使用一个编译器编译成两个不同的程序集吗?或者我可以将一个编译作为对另一编译的参考吗?(是否有一个 MetadataReference 我可以提供给 Compilation.AddReference 指向另一个编译?)

PS:我还没有尝试过在我将它们添加到编译或使用 SyntaxTree.FilePath 属性和一些映射之前将某种元数据(例如开头的注释节点)添加到语法树中,以使用它我的生成器中的信息来判断定义的类型是来自“特殊”还是“普通”。我宁愿不做这样的事情,因为它会很快变得混乱(实际上,我有大约 20 个 dll)。

4

1 回答 1

3

所以编译和构建的程序集之间存在 1:1 的对应关系,因此如果在分析过程中需要同时表示两个程序集,则需要进行两次编译。要在它们之间添加引用,只需执行操作compilation.AddReference(new CompilationReference(sourceCompilation)),符号应该按照您的预期导入。不要忘记编译是不可变的,所以如果你曾经 fork sourceCompilation,你可能也必须 fork 你的引用编译。

在任何给定的符号上,都有一个属性 ContainingAssembly 可以让您回到符号来源的程序集。确保您在编译中正确设置了输出名称,这样您就可以弄清楚这一点。

于 2013-05-03T21:34:24.413 回答