2017-04-27 37 views
1

lambda表达式我想写像这样使用的CodeDOM:净CodeDom中 - .NET实现

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

我不知道这个是什么在CodeDom中(System.CodeDom)的等价物。

+1

这个答案可能是你的情况http://stackoverflow.com/a/3273307/920557有用 –

+1

的'X => x.Id == 2'被编译并传递给扩展的方法代表。在这种情况下'Func '请参阅https://msdn.microsoft.com/en-us/library/system.linq.enumerable.where(v=vs.110).aspx –

+0

以下是CodeDom的表达式示例转换https://csharphardcoreprogramming.wordpress.com/2014/01/15/reflection-part-5-professional-codedom-lambda-expression-tree/ –

回答

3

简答:CodeDOM不支持lambda表达式。

长答案:CodeDOM没有任何支持lambda表达式,所以你将不得不使用一种解决方法。一些选项:

  1. 使用CodeSnippetExpression

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

    这样,你就失去了大部分的使用的CodeDOM的优势,但它很容易,你可以做你想要什么。

  2. 创建从拉姆达含有代码的方法,然后使用委托引用它:

    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) 
    

    这些问题与该方法的缺点是它产生不同(可读性较差)代码,如果查询必须是表达式,通常是因为您使用的是类似于Entity Framework的IQueryable<T>,所以它不起作用。

  3. 切换到代码生成库支持lambda表达式,如罗斯林:

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

    这里最明显的缺点是,你将不得不重写代码。