c# - 如何使用 Roslyn 在 C# 中获取 lambda 类型?

标签 c# roslyn roslyn-code-analysis

我正在用 roslyn 编写我的代码修复程序。我希望它以这样的方式工作:
之前:

IEnumerable<int> list = new List<int> {1, 2, 3, 4};
list = list.Where(x => x%2 == 0);

之后:

...
IEnumerable<int> list = new List<int> {1, 2, 3, 4};
list = list.Where(lambdaMethod);
...
private static bool lamdaMethod(int x)
{
    return x % 2 == 0;
}

问题是我找不到获取方法和参数类型的返回类型的正确方法。
我的分析器模板方法:

public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            // TODO: Replace the following code with your own analysis, generating a CodeAction for each fix to suggest
            var diagnostic = context.Diagnostics.FirstOrDefault();
            var diagnosticSpan = diagnostic.Location.SourceSpan;

            // Find the type declaration identified by the diagnostic.
            var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf()
                .OfType<LambdaExpressionSyntax>().FirstOrDefault();
            if (declaration == null)
                return;
            // Register a code action that will invoke the fix.

            context.RegisterCodeFix(
                CodeAction.Create(
                    title: $"{"Just Title"}",
                    createChangedDocument: c => MakeLambdaOptimization(context.Document, declaration, c),
                    equivalenceKey: nameof(CodeFixResources.CodeFixTitle)),
                diagnostic);
        }

如您所见,我正在与 LambdaExpressionSyntax 合作。还有SimpleLambdaExpressionSyntaxParenthesizedLambdaExpressionSyntax这帮助我得到 ParameterSyntax 。在 ParameterSyntax我可以找到Type ,但它是 null 并且我得到 NullReferenceException。
我尝试获取 lambda 的整个类型(例如 Func<int, bool> ),我想这会对我有帮助。我该怎么做?我听说过 SemanticModel,但不知道如何使用

最佳答案

您可以使用SemanticModel.GetSymbolInfo(ExpressionSyntax)来获取lambda符号。从 lambda 符号中您可以找到所需的信息(返回类型和参数类型)。这是一个代码片段(为了简单起见,在控制台应用程序而不是代码修复程序的上下文中编写 - 您将能够使其适用于代码修复程序):

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

// You don't need to create or get a compilation yourself. I'm creating it manually since I'm in a console app.
CSharpCompilation comp = CSharpCompilation.Create(null, new[] { SyntaxFactory.ParseSyntaxTree("System.Func<int, bool> f = x => x % 2 == 0;") }, new[] { MetadataReference.CreateFromFile(typeof(Func<>).Assembly.Location) });

// You already have the LambdaExpressionSyntax, ignore the following two lines, which again because I'm in a console app.
var root = comp.SyntaxTrees[0].GetRoot();
var lambda = root.DescendantNodes().OfType<LambdaExpressionSyntax>().Single();

// Here you'll need to get a semantic model via 'await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);'
var model = comp.GetSemanticModel(lambda.SyntaxTree);

// That's the core of what you want to do.
if (model.GetSymbolInfo(lambda).Symbol is IMethodSymbol lambdaSymbol)
{
    // prints 'bool'
    Console.WriteLine(lambdaSymbol.ReturnType.ToDisplayString());
    foreach (var parameter in lambdaSymbol.Parameters)
    {
        // prints 'int' (loop is entered once since my lambda has a single parameter).
        Console.WriteLine(parameter.Type.ToDisplayString());
    }
}

关于c# - 如何使用 Roslyn 在 C# 中获取 lambda 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71818145/

相关文章:

c# - 检查是否加载了导航属性

c# - 如何将 "using static"指令用于动态生成的代码?

c# - 我可以在带有 .NET 4.7 的 Visual Studio 2017 中使用 "Roslyn"吗?

c# - lock 语句中还需要 volatile 吗?

c# - 自动更新 SQL Server 数据库架构

c# - 使用 TimeSpan 作为定时器间隔

c# - 将 Reflection.Emit 转换为 Roslyn

c# - 用方法替换 C# 代码中的所有变量

c# - Roslyn 模型是否以 C#/VB.NET 为中心以至于现在和将来都无法进行 XAML 分析?

c# - Roslyn 分析器未检测 While 表达式