首页 > 解决方案 > 构造表达式树以调用 IQueryable 集合上的 Any 方法(嵌套查询)

问题描述

我正在尝试构建一个扩展方法来IQueryable检查导航属性中是否有任何匹配的元素。我在下面的代码之外做的是迭代一个类型的属性并检查该属性是否是使用IModel.

我在试图弄清楚如何为一对多关系构建表达式树时遇到问题。我想要实现的是类似Entity.Collections.Any(Collection => Collection.Name == 'Filter')的,然后是主查询的 where 子句。内部子句是在下面的示例之外构建的,但我相信错误发生在到达该表达式之前。

我认为 the 的委托类型Lambda可能构造错误,因为它没有返回bool,它正在返回IEnumerable<Collection>,但如果不是这样,我无法弄清楚它应该如何构造。

我正在尝试遵循Microsoft 文档中的指南。

试图解决上述问题的代码行:

if (typeof(IEnumerable).IsAssignableFrom(targetType))
{
    var targetEntity = targetType.GetGenericArguments().First();
    var subArgument = Expression.Parameter(targetEntity, targetEntity.Name);

    var delegateType = typeof(Func<,>).MakeGenericType(targetEntity, typeof(bool));
    var lambda = Expression.Lambda(delegateType, innerClause, Expression.Parameter(targetEntity));

    Expression.Call(
        typeof(Queryable),
        "Any",
        new Type[] { targetEntity },
        Expression.Property(argument, property.Name),
        lambda
    );
}

我在尝试创建Expression.Call.

Exception thrown: 'System.InvalidOperationException' in System.Linq.Expressions.dll: 'No generic method 'Any' on type 'System.Linq.Queryable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic. '

我还尝试获取 any 方法并调用它:

var anyMethod = typeof(Queryable)
    .GetMethods()
    .Where(m => m.Name == "Any" && m.IsGenericMethodDefinition)
    .Where(m => m.GetParameters().ToList().Count == 2)
    .First();

var genericMethod = anyMethod.MakeGenericMethod(entityType);

genericMethod.Invoke(Expression.Property(argument, property.Name), new object[] { innerClause, subArgument });

然后我得到了这个错误:

Exception thrown: 'System.ArgumentException' in System.Private.CoreLib.dll: 'Object of type 'System.Linq.Expressions.MethodCallExpression3' cannot be converted to type 'System.Linq.IQueryable1[收藏]'.'`

任何帮助是极大的赞赏!

标签: .net-corelambdareflectionef-core-3.1

解决方案


好吧,也许这个问题有点不清楚,因为我不知道该怎么问,但是,如果有人偶然发现这个问题,我就是这样解决的:

if (typeof(IEnumerable).IsAssignableFrom(targetType))
{
    var targetEntity = targetType.GetGenericArguments().First();
    var subArgument = Expression.Parameter(targetEntity, targetEntity.Name);

    var anyMethod = typeof(Enumerable)
        .GetMethods()
        .Where(m => m.Name == "Any" && m.IsGenericMethodDefinition)
        .Where(m => m.GetParameters().ToList().Count == 2)
        .First();

    anyMethod = GetAnyMethod().MakeGenericMethod(targetType);

    Expression.Call(anyMethod, Expression.MakeMemberAccess(argument, property), Expression.Lambda(x, subArgument));
}

所以,主要问题是我试图在而不是调用方法QueryableEnumerable因为我是在属性而不是可查询对象上调用方法,所以我应该这样做。


推荐阅读