.Net CodeDom - Implement lambda expression in .net

℡╲_俬逩灬. 提交于 2020-01-04 05:49:07

问题


I want to write something like this using CodeDom:

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

I don't know what is the equivalent of this in CodeDom (System.CodeDom).


回答1:


Short answer: CodeDOM doesn't have any support for lambdas.

Long answer: CodeDOM doesn't have any support for lambdas, so you will have to use a workaround. Some options:

  1. Use CodeSnippetExpression:

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

    This way, you lose most of the advantages of using CodeDOM, but it's easy and you can do exactly what you want.

  2. Create a method containing code from the lambda and then use a delegate referencing it:

    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"))
    

    This generates code like:

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

    The issues with this approach is that it generates different (and less readable) code than what you wanted and that it won't work if the query has to be an expression, usually because you're using IQueryable<T> with something like Entity Framework.

  3. Switch to a code generation library that supports lambdas, like 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))))))))
    

    Or using 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))))
    

    The obvious disadvantage here is that you will have to rewrite your code.



来源:https://stackoverflow.com/questions/43658351/net-codedom-implement-lambda-expression-in-net

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!