需要帮助将“Any()”lambda转换为表达式树

时间:2017-09-24 17:08:14

标签: c# linq lambda tree expression

请考虑以下事项。 (这有效,但我需要将帐户作为字符串传递。帐户是帐户列表)

repo = repo.Where(x => x.Accounts.Any(p => p.Id == 1));

这是我到目前为止所做的,但我似乎无法在最后将它们连接在一起。

        var parameterExp = Expression.Parameter(typeof(Car), "x");
        Expression propertyExp = Expression.Property(parameterExp, "Accounts");

        //Type elementType = propertyExp.Type.GetGenericArguments()[0];

        MethodInfo AnyMethod = typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static).First(m => m.Name == "Any");

        var parameterExp2 = Expression.Parameter(typeof(Car), "p");

        var idExpr = Expression.PropertyOrField(parameterExp2, "Id");

        MethodInfo method = typeof(long).GetMethod("Equals", new[] { typeof(long) });
        var _relatedToId = Expression.Constant(relatedToId, typeof(long));
        var equalsMethodExp = Expression.Call(idExpr, method, _relatedToId);

        // This is where it breaks. I can't seem to wire it together correctly.
        var call = Expression.Call(
            AnyMethod,
            propertyExp,
            equalsMethodExp);

        Expression<Func<Car, bool>> predicate = Expression.Lambda<Func<Car, bool>>(call, parameterExp);

        // Need to return x => x.Accounts.Any(p => p.Id.Equals(1))
        return predicate;

提前致谢

1 个答案:

答案 0 :(得分:0)

你有几个错误:

  • 首先,取消注释下面的行

    Type elementType = propertyExp.Type.GetGenericArguments()[0];
    
  • 其次,您无法正确检索MethodInfo的{​​{1}}。您需要包含两个参数(source,func)的信息,并且您需要获得封闭类型的任意Any而非开放Any<Account>

    Any<>
  • 第三,MethodInfo AnyMethod = typeof(Enumerable) .GetMethods(BindingFlags.Public | BindingFlags.Static) .First(m => m.Name == "Any" && m.GetParameters().Length > 1); var closedAnyMethod = AnyMethod.MakeGenericMethod(elementType); 的类型不正确。它应该是parameterExp2而不是Account

    Car
  • 第四,您应该将 Equals 方法的var parameterExp2 = Expression.Parameter(elementType, "p"); 转换为lambda表达式。您无法直接传递等于&#39;将表达式调用到MethodCallExpression,因为Any获取Any作为参数:

    Func<T, bool>
  • 最后,您只需要调用var equalsMethodExp = Expression.Call(idExpr, method, _relatedToId); var lambdaAny = Expression.Lambda(typeof(Func<,>).MakeGenericType(elementType, typeof(bool)), equalsMethodExp, parameterExp2); 的另一个覆盖:

    Expression.Call

如果您想获得完整的代码,请告诉我。