C# 使用Contains构建Lambda表达式

C# 使用Contains构建Lambda表达式,c#,linq-to-entities,expression,C#,Linq To Entities,Expression,我在将简单linq查询转换为Lambda表达式时遇到问题 我的查询如下所示: int[] array = List<int> array2 = sql.OfType<Table1>().Select(x=>x.ID).Take(10).ToList(); var result = sql.OfType<Table1>().Where(x => array.Contains(x.ID)).Take(10).ToList(); 我已经转换了第一个la

我在将简单linq查询转换为Lambda表达式时遇到问题

我的查询如下所示:

int[] array = List<int> array2 = sql.OfType<Table1>().Select(x=>x.ID).Take(10).ToList();
var result = sql.OfType<Table1>().Where(x => array.Contains(x.ID)).Take(10).ToList();
我已经转换了第一个lambda:

public static Expression<Func<T, int>> SelectExpression<T>(string fieldName)
{
    ParameterExpression param = Expression.Parameter(typeof(T), "x");
    MemberExpression selection = Expression.PropertyOrField(param, fieldName);
    var lambdaExp = Expression.Lambda<Func<T, int>>(selection, param);
    return lambdaExp;
}
公共静态表达式SelectExpression(字符串字段名)
{
ParameterExpression param=表达式参数(typeof(T),“x”);
MemberExpression selection=Expression.PropertyOrField(参数,字段名);
var lambdaExp=Expression.Lambda(选择,参数);
返回lambdaExp;
}
但第二个问题仍然存在:

static Expression<Func<T, bool>> InExpression<T>(string propertyName,IEnumerable<int> array)
{
    System.Reflection.MethodInfo containsMethod = typeof(IEnumerable<int>).GetMethod("Contains");
    ParameterExpression param = Expression.Parameter(typeof(T), "x");
    MemberExpression member = Expression.PropertyOrField(param, propertyName);//x.{property}
    var constant = Expression.Constant(3);
    var body = Expression.GreaterThanOrEqual(member, constant); //x.{property} >= 3 but I need  array.Contains(x.{property})
    var finalExpression = Expression.Lambda<Func<T, bool>>(body, param);
    return finalExpression;
}
静态表达式非表达式(字符串属性名称,IEnumerable数组)
{
System.Reflection.MethodInfo containsMethod=typeof(IEnumerable).GetMethod(“Contains”);
ParameterExpression param=表达式参数(typeof(T),“x”);
MemberExpression member=Expression.PropertyOrField(param,propertyName);//x.{property}
var常数=表达式常数(3);
var body=Expression.GreaterThanOrEqual(member,constant);//x.{property}>=3但我需要array.Contains(x.{property})
var finalExpression=表达式.Lambda(body,param);
返回最终压力;
}
有谁能帮我把lambda表达式
x=>array2.Contains(x.ID)
转换成非表达式方法吗


另外,我非常感谢您提供有关创建这些类型表达式的文章/教程的链接。

可能类似于:

static Expression<Func<T, bool>> InExpression<T>(
    string propertyName, IEnumerable<int> array)
{
    var p = Expression.Parameter(typeof(T), "x");
    var contains = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
        .Single(x => x.Name == "Contains" && x.GetParameters().Length == 2)
        .MakeGenericMethod(typeof(int));
    var property = Expression.PropertyOrField(p, propertyName);
    var body = Expression.Call(contains, Expression.Constant(array), property);
    return Expression.Lambda<Func<T, bool>>(body, p);
}
与:

类表达式状态
{
公共IEnumerable数组;
}

太棒了。Txh的帮助和inf它不是一个问题,你能再写一个例子的无表达式方法,看起来尽可能接近代码的编译器生成?我只是试着去理解这个“修正”,希望以后我能理解;现在已经离开桌面了。希望你能抽出几分钟的时间this@DespeiL补充;注意,它创建了一个“capture”类来保存
数组
,我用
ExpressionState
来表示它。然而,如果你是手工操作,你通常可以避免这种情况;这仅仅是为了尊重一些关于变量生存期等的语言语义,即如果在创建lambdaThx之后为所有帮助重新分配
状态
会发生什么,但我会让您参考,特别是关于。
static Expression<Func<T, bool>> InExpression<T>(string propertyName,IEnumerable<int> array)
{
    System.Reflection.MethodInfo containsMethod = typeof(IEnumerable<int>).GetMethod("Contains");
    ParameterExpression param = Expression.Parameter(typeof(T), "x");
    MemberExpression member = Expression.PropertyOrField(param, propertyName);//x.{property}
    var constant = Expression.Constant(3);
    var body = Expression.GreaterThanOrEqual(member, constant); //x.{property} >= 3 but I need  array.Contains(x.{property})
    var finalExpression = Expression.Lambda<Func<T, bool>>(body, param);
    return finalExpression;
}
static Expression<Func<T, bool>> InExpression<T>(
    string propertyName, IEnumerable<int> array)
{
    var p = Expression.Parameter(typeof(T), "x");
    var contains = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
        .Single(x => x.Name == "Contains" && x.GetParameters().Length == 2)
        .MakeGenericMethod(typeof(int));
    var property = Expression.PropertyOrField(p, propertyName);
    var body = Expression.Call(contains, Expression.Constant(array), property);
    return Expression.Lambda<Func<T, bool>>(body, p);
}
using System.Linq;
using System;
using System.Linq.Expressions;
using System.Collections.Generic;

public class C {
    static Expression<Func<Foo, bool>> InExpression<T>(
        string propertyName,IEnumerable<int> array)
    {
        return x => array.Contains(x.Id);
    }
}

class Foo {
    public int Id {get;set;}   
}
private static Expression<Func<Foo, bool>> InExpression<T>(string propertyName, IEnumerable<int> array)
{
    C.<>c__DisplayClass0_0<T> <>c__DisplayClass0_ = new C.<>c__DisplayClass0_0<T>();
    <>c__DisplayClass0_.array = array;
    ParameterExpression parameterExpression = Expression.Parameter(typeof(Foo), "x");
    Expression arg_77_0 = null;
    MethodInfo arg_77_1 = methodof(IEnumerable<!!0>.Contains(!!0));
    Expression[] expr_38 = new Expression[2];
    expr_38[0] = Expression.Field(Expression.Constant(<>c__DisplayClass0_, typeof(C.<>c__DisplayClass0_0<T>)), fieldof(C.<>c__DisplayClass0_0<T>.array));
    Expression[] expr_5F = expr_38;
    expr_5F[1] = Expression.Property(parameterExpression, methodof(Foo.get_Id()));
    Expression arg_86_0 = Expression.Call(arg_77_0, arg_77_1, expr_5F);
    ParameterExpression[] expr_82 = new ParameterExpression[1];
    expr_82[0] = parameterExpression;
    return Expression.Lambda<Func<Foo, bool>>(arg_86_0, expr_82);
}
private static Expression<Func<Foo, bool>> InExpression<T>(string propertyName, IEnumerable<int> array)
{
    ExpressionState state = new ExpressionState();
    state.array = array;
    ParameterExpression parameterExpression = Expression.Parameter(typeof(Foo), "x");
    MethodInfo contains = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
        .Single(x => x.Name == nameof(Enumerable.Contains) && x.GetParameters().Length == 2)
        .MakeGenericMethod(typeof(int));
    Expression[] callArgs = new Expression[2];
    callArgs[0] = Expression.Field(Expression.Constant(state, typeof(ExpressionState)), nameof(ExpressionState.array));
    callArgs[1] = Expression.Property(parameterExpression, propertyName);
    Expression body = Expression.Call(null, contains, callArgs);
    ParameterExpression[] parameters = new ParameterExpression[1];
    parameters[0] = parameterExpression;
    return Expression.Lambda<Func<Foo, bool>>(body, parameters);
}
class ExpressionState
{
    public IEnumerable<int> array;
}