存在ProjectReferences时MetadataReferences未填充的技术咨询
我之前也碰到过类似的问题,其实这是MSBuildWorkspace的设计逻辑导致的,不是什么bug,咱们来拆解下具体原因:
项目引用的优先级处理:当项目包含
ProjectReferences时,MSBuildWorkspace会把项目间的依赖关系放在优先位置。它认为项目引用应该通过ProjectReferences集合来访问,而不是把依赖项目的编译产物混入MetadataReferences里。只有当项目没有任何项目引用时,Workspace才会直接加载所有程序集引用(包括mscorlib这类系统库),因为此时没有项目依赖需要特殊处理。延迟加载的性能考量:这其实是一种性能优化策略。如果Workspace在加载时就把所有依赖的程序集都填充到
MetadataReferences里,对于大型解决方案来说会非常耗时,甚至导致加载卡顿。所以它选择了延迟加载,只有在需要的时候(比如你手动处理项目引用的编译输出时)才去获取对应的程序集引用。编译正常的底层逻辑:你说编译能正常执行,这是因为实际编译时MSBuild会处理完整的项目依赖链——它会先编译被引用的项目,然后把其输出程序集作为引用传递给当前项目的编译器。这个过程和Workspace加载时的逻辑是完全分开的,Workspace的
MetadataReferences更多是给代码分析、语法树处理这类场景用的,不是编译执行的依赖路径。
如果你需要获取带ProjectReferences项目的实际程序集引用,可以手动遍历项目引用并构建MetadataReference,示例代码如下:
// 假设当前处理的项目为targetProject foreach (var projectRef in targetProject.ProjectReferences) { var referencedProject = solution.GetProject(projectRef.ProjectId); if (referencedProject == null) continue; // 获取引用项目的编译输出路径和程序集名称 var outputDir = referencedProject.GetPropertyValue("OutputPath"); var assemblyName = referencedProject.GetPropertyValue("AssemblyName") + ".dll"; var assemblyPath = Path.Combine(referencedProject.DirectoryPath, outputDir, assemblyName); // 创建对应的MetadataReference var metadataReference = MetadataReference.CreateFromFile(assemblyPath); // 可将其添加到自定义集合中用于后续分析 }
内容的提问来源于stack exchange,提问作者nikolaia

