我有一个带有两个输出dll的解决方案(实际上更多,但让我们保持简单)。项目“特殊”引用项目“共同”。
我尝试编写一个代码生成器来解析“Special”中的一些文件,并将生成的存根代码放入项目“Common”中。为了处理这个循环引用,我需要处理不能编译的代码。所以我正在使用Roslyn。
生成器需要根据继承信息替换某些类型,因此我需要构建一个编译单元来访问语义模型。另外,我需要根据类型的来源替换一些东西(无论它们是在“特殊”还是“普通”中定义。或者更精确:基于全局汇编属性)。
生成器必须能够作为MSBuild任务运行。
我尝试了两种方法来设置我的环境,而且我很困惑:
我试图在Generator中加载我的解决方案。这失败是因为“无法将透明代理强制转换为'Roslyn.Utilities.SerializableDataStorage'”。然后我尝试从头开始创建解决方案,添加IProjects和IDocuments,我已经尝试了this answer中建议的LoadProjectFromCommandLineArguments,但似乎没有什么对我有用,从MSBuild运行时我得到了同样的异常(它运行正常通过控制台启动时。)
任何人都知道如何处理SerializableDataStorage异常?
我尝试创建一个编译并添加我所有的cs源代码。但现在我找不到办法知道我的符号是来自汇编“特别”还是“共同”。
我可以使用一个编译编译成两个不同的程序集吗?或者我可以将一个编译作为参考传递给另一个编译吗? (是否有MetadataReference我可以提供给指向另一个编译的Compilation.AddReference?)
PS:我还没有尝试的是在将语法树添加到编译之前将一些元数据(例如一开始的注释节点)添加到语法树中,或者使用SyntaxTree.FilePath属性和一些映射,在我的生成器中使用此信息来判断定义的类型是来自“特殊”还是“公共”。我宁愿不会做这样的事情,因为它会很快变得混乱(实际上,我有大约20个dll)。
答案 0 :(得分:3)
因此,编译和构建的程序集之间存在1:1的对应关系,因此如果需要在分析期间表示两个程序集,则需要进行两次编译。要在它们之间添加引用,只需执行compilation.AddReference(new CompilationReference(sourceCompilation))
并且符号应该导入您期望的方式。不要忘记编译是不可变的,所以如果你曾经使用sourceCompilation,你也可能需要对你的引用编译进行分支。
在任何给定的符号上,有一个属性ContainingAssembly可以让你回到符号来自的汇编。确保在编辑中正确设置输出名称,这样可以解决这个问题。