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

时间:2017-04-27 12:50:30

标签: c# .net codedom

我想用CodeDom写这样的东西:

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

我不知道CodeDom(System.CodeDom)中的等价物。

1 个答案:

答案 0 :(得分:5)

简短回答:CodeDOM对lambdas没有任何支持。

答案很长:CodeDOM对lambdas没有任何支持,所以你必须使用一种解决方法。一些选择:

  1. 使用CodeSnippetExpression

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

    这样,您失去了使用CodeDOM的大部分优势,但它很简单,您可以完全按照自己的意愿行事。

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

    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)
    

    这种方法的问题在于它生成的代码与您想要的代码不同(且可读性较差),并且如果查询必须是表达式,它通常会因为您正在使用{而无法工作{1}}使用类似于Entity Framework的内容。

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

    IQueryable<T>

    或使用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

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