Roslyn CompletionService无法推断foreach隐式变量类型问题
问题根因
foreach循环隐式变量补全失效,是两个配置缺失共同导致的:
- 元数据引用不全:你只加载了核心运行时和自定义业务程序集,没有加载
System.Collections、System.Runtime等定义泛型集合类型的基础程序集。Roslyn推断foreach变量类型时,需要解析IEnumerable<T>的GetEnumerator()方法返回值、Current属性类型,缺少对应元数据时无法完成类型推导;而普通变量赋值的类型推断直接读取属性的声明类型,不依赖集合相关逻辑,所以能正常工作。 - MEF服务加载不全:你只在默认MEF程序集列表里加了自定义业务程序集,没有加载C#语义分析、补全服务对应的Features程序集。foreach场景的隐式类型补全逻辑在C# Features程序集中,Visual Studio默认加载所有相关Features程序集,所以可以正常出补全结果。
修复方案
按以下步骤调整配置即可:
- 补全必要的元数据引用
不要只加载object类型所在的核心程序集,把泛型、集合相关的基础程序集都加入引用列表:
var runtimeRoot = Path.GetDirectoryName(typeof(object).Assembly.Location); var metadataRefs = new List<MetadataReference> { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(Path.Combine(runtimeRoot, "System.Runtime.dll")), MetadataReference.CreateFromFile(Path.Combine(runtimeRoot, "System.Collections.dll")), MetadataReference.CreateFromFile(Path.Combine(runtimeRoot, "System.Linq.dll")), MetadataReference.CreateFromFile(typeof(ScriptEngine).Assembly.Location) }; // 后续把这个metadataRefs传给WithMetadataReferences即可
- 补全MEF加载的程序集列表
把Roslyn C#编译、补全服务对应的程序集加入MEF加载列表:
var assemblies = new List<Assembly>(MefHostServices.DefaultAssemblies); // 加入C#编译核心、补全服务核心程序集 assemblies.Add(typeof(CSharpCompilation).Assembly); assemblies.Add(typeof(CompletionService).Assembly); assemblies.Add(typeof(ScriptEngine).Assembly); var host = MefHostServices.Create(assemblies); this.workspace = new AdhocWorkspace(host);
- 移除不必要的编译选项配置
你当前给submission(脚本)项目手动指定了OutputKind.DynamicallyLinkedLibrary,这会和脚本模式的语义解析逻辑冲突,去掉该配置,用submission项目默认的输出类型即可。
验证方式
调整配置后,可以在调用GetCompletionsAsync前先校验语义模型的推断结果:
var syntaxRoot = await document.GetSyntaxRootAsync(); // 找到光标位置对应的语法Token var token = syntaxRoot.FindToken(position); var semanticModel = await document.GetSemanticModelAsync(); // 获取光标位置的类型信息 var typeInfo = semanticModel.GetTypeInfo(token.Parent); // 如果typeInfo.Type显示为Measure类型,说明类型推断正常,补全服务会正常返回成员列表
额外注意:如果你的脚本支持顶层变量、模式匹配等新语法,要确保
CSharpParseOptions指定的LanguageVersion和你引用的Roslyn版本匹配,避免语法解析失败导致后续补全失效。
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

