c# - .Net CodeDom - 在 .net 中实现 lambda 表达式

标签 c# .net codedom

我想使用 CodeDom 编写这样的内容:

.Where(x => x.Id == 2);

我不知道 CodeDom (System.CodeDom) 中与此等效的是什么。

最佳答案

简短回答:CodeDOM 不支持 lambda。

长答案:CodeDOM 不支持 lambda,因此您必须使用解决方法。一些选项:

  1. 使用CodeSnippetExpression :

    new CodeMethodInvokeExpression(
        collectionExpression, "Where", new CodeSnippetExpression("x => x.Id == 2"));
    

    这样,您就失去了使用 CodeDOM 的大部分优势,但它很简单,您可以做您想做的事情。

  2. 创建一个包含 lambda 代码的方法,然后使用引用它的委托(delegate):

    var lambdaMethod = new CodeMemberMethod
    {
        Name = "IsIdTwo",
        Parameters =
        {
            new CodeParameterDeclarationExpression(
                new CodeTypeReference("YourEntityType"), "x")
        },
        Statements =
        {
            new CodeMethodReturnStatement(
                new CodeBinaryOperatorExpression(
                    new CodePropertyReferenceExpression(
                        new CodeVariableReferenceExpression("x"), "Id"),
                    CodeBinaryOperatorType.ValueEquality,
                    new CodePrimitiveExpression(2)))
        }
    };
    
    …
    
    new CodeMethodInvokeExpression(
        collectionExpression, "Where", new CodeMethodReferenceExpression(null, "IsIdTwo"))
    

    这会生成如下代码:

    private void IsIdTwo(YourEntityType x) {
        return (x.Id == 2);
    }
    
    …
    
    collection.Where(IsIdTwo)
    

    这种方法的问题在于,它会生成与您想要的不同(且可读性较差)的代码,并且如果查询必须是表达式,则它将无法工作,通常是因为您使用的是 IQueryable<T>使用 Entity Framework 之类的东西。

  3. 切换到支持 lambda 的代码生成库,例如 Roslyn:

    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp;
    using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
    
    …
    
    InvocationExpression(
        MemberAccessExpression(
            SyntaxKind.SimpleMemberAccessExpression,
            IdentifierName("collection"),
            IdentifierName("Where")),
        ArgumentList(
            SingletonSeparatedList(
                Argument(
                    SimpleLambdaExpression(
                        Parameter(Identifier("x")),
                        BinaryExpression(
                            SyntaxKind.EqualsExpression,
                            MemberAccessExpression(
                                SyntaxKind.SimpleMemberAccessExpression,
                                IdentifierName("x"),
                                IdentifierName("Id")),
                            LiteralExpression(
                                SyntaxKind.NumericLiteralExpression, Literal(2))))))))
    

    或者使用SyntaxGenerator :

    var generator = SyntaxGenerator.GetGenerator(new AdhocWorkspace(), LanguageNames.CSharp);
    
    generator.InvocationExpression(
        generator.MemberAccessExpression(generator.IdentifierName("collection"), "Where"),
        generator.ValueReturningLambdaExpression(
            "x",
            generator.ValueEqualsExpression(
                generator.MemberAccessExpression(generator.IdentifierName("x"), "Id"),
                generator.LiteralExpression(2))))
    

    这里明显的缺点是您必须重写代码。

关于c# - .Net CodeDom - 在 .net 中实现 lambda 表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43658351/

相关文章:

c# - 如何检测用户是否离开键盘?

c# - 从列表中选择数据并显示在listBox中,C#

c# - 您能否通过一个简单的现实生活示例非常简要地解释什么是 CodeDOM 及其用途?

vb.net - 删除从 Codedom 生成的代码中的项目

c# - 当编译器不需要也不使用 CodeNamespaceImport 时,它的意义何在?

c# - 为什么Web Api(.Net Core)总是返回JSON而忽略ContentType中的值?

c# - Outlook Exchange 帐户仅发送 5 条消息

asp.net - GraphQL.NET 如何将枚举添加到 GraphQL 类型

.net - 在 ASP.NET 动态数据/LINQ to SQL 中启用编辑主键字段

c# - 命名空间中不存在自定义控件?