我想用 CodeDom 写这样的东西:

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

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

最佳答案

简短回答:CodeDOM 不支持 lambda。

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

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

    这样,您将失去使用 CodeDOM 的大部分优势,但它很容易,您可以完全按照自己的意愿行事。
  • 创建一个包含来自 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 之类的东西一起使用。
  • 切换到支持 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/

    10-10 02:04