Roslyn CodeFix如何获取MSBuild属性、全局using及配置单元测试
1. 读取MSBuild全量属性与ImplicitUsings配置
Roslyn Analyzer默认无法直接读取Directory.Build.props或.csproj里的MSBuild属性,需要先通过规则将需要的属性暴露给编译器,再通过Analyzer接口读取:
- 第一步:在Analyzer项目中新增一个
.props文件,设置为打包到NuGet包的build目录,内容如下:<Project> <ItemGroup> <!-- 把需要读取的MSBuild属性全部通过CompilerVisibleProperty声明 --> <CompilerVisibleProperty Include="ImplicitUsings" /> <CompilerVisibleProperty Include="其他你需要读取的属性名" /> </ItemGroup> </Project> - 第二步:在Analyzer代码中通过
AnalyzerConfigOptionsProvider读取属性:public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); context.RegisterCompilationStartAction(ctx => { var globalOptions = ctx.Options.AnalyzerConfigOptionsProvider.GlobalOptions; // 读取ImplicitUsings配置 if (globalOptions.TryGetValue("build_property.ImplicitUsings", out var implicitUsingsVal)) { bool isImplicitUsingsOn = implicitUsingsVal.Equals("enable", StringComparison.OrdinalIgnoreCase) || implicitUsingsVal.Equals("true", StringComparison.OrdinalIgnoreCase); // 执行对应逻辑 } // 所有声明过的MSBuild属性都可以通过`build_property.属性名`的Key读取 }); }
2. 获取项目全部Global Usings
无需自行解析MSBuild配置,Roslyn已经把所有来源的全局Using汇总到了Compilation对象的GlobalImports属性中,覆盖范围包括:SDK隐式生成的全局Using、.csproj中<Using>节点配置的全局Using、代码中声明的global using:
// 在CompilationStartAction上下文中直接读取 List<string> allGlobalUsings = ctx.Compilation.GlobalImports .Select(import => import.Namespace) .ToList();
3. Microsoft.CodeAnalysis.Testing 单元测试注入MSBuild属性
在测试用例中通过SolutionTransforms注入全局配置,即可模拟MSBuild属性的场景:
var test = new CSharpAnalyzerTest<你的Analyzer类名, DefaultVerifier> { TestCode = @"// 你的测试代码", SolutionTransforms = { (solution, projectId) => { var propertyDict = new Dictionary<string, string> { {"build_property.ImplicitUsings", "enable"}, // 其他需要注入的MSBuild属性都在这里添加 }; return solution.WithAnalyzerConfigOptions(solution.GetProject(projectId), propertyDict); } } }; // 如果需要模拟ImplicitUsings开启后的全局Using,直接添加即可 test.TestState.GlobalUsings.Add("System"); test.TestState.GlobalUsings.Add("System.Collections.Generic"); await test.RunAsync();
内容的提问来源于stack exchange,提问作者LoadIt
相关产品推荐
相关产品推荐

