如何使用Roslyn在C#中获得类型的lambda?

发布于 2025-01-20 17:42:13 字数 2009 浏览 4 评论 0原文

我正在用罗斯林(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。还有SimpleLambdaexpressyNtax括号>括号>括号lambdaexpressionsyntax,可以帮助我获得parametersyntax。在parametersyntax中,我可以找到type,但它是null,我得到了NullReferenceException。
我试图获得全部类型的lambda(例如func&lt; int,bool&gt;),我想这对我有帮助。我该怎么做?我听说过semanticmodel,但我不知道如何使用它

I'm writing my codefixer with roslyn. I want it to work in such way:
Before:

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

After:

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

The problem is that I can't find the proper way to get return type for the method and type of argument.
My method from analyzer template:

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: 
quot;{"Just Title"}",
                    createChangedDocument: c => MakeLambdaOptimization(context.Document, declaration, c),
                    equivalenceKey: nameof(CodeFixResources.CodeFixTitle)),
                diagnostic);
        }

As you see, I'm working with LambdaExpressionSyntax. There are also SimpleLambdaExpressionSyntax and ParenthesizedLambdaExpressionSyntax which help me to get ParameterSyntax. In the ParameterSyntax I can find Type, but it's null and I get NullReferenceException.
I tried to get the whole type of lambda (e.g. Func<int, bool>), I guess it would help me. How can I do it? I've heard about SemanticModel, but I don't know how to use it

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

骷髅 2025-01-27 17:42:13

您可以使用 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());
    }
}

You can use SemanticModel.GetSymbolInfo(ExpressionSyntax) to get the lambda symbol. From the lambda symbol you can find the information you need (return type and parameter types). Here is a code snippet (written in the context of a Console Application instead of a codefix for simplicity - you'll be able to get it working for codefixes):

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());
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文