C# 动态构建linq谓词的扩展方法

C# 动态构建linq谓词的扩展方法,c#,linq,extension-methods,C#,Linq,Extension Methods,我有这个扩展方法 public static IQueryable<T> SearchBy<T>(this IQueryable<T> source, SearchCriteria criteria) { //throw an error if the source is null if (source == null) { throw new ArgumentNu

我有这个扩展方法

        public static IQueryable<T> SearchBy<T>(this IQueryable<T> source, SearchCriteria criteria)
    {
        //throw an error if the source is null
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }

        ParameterExpression parameter = Expression.Parameter(source.ElementType, string.Empty);
        var property = Expression.Equal(Expression.PropertyOrField(parameter, criteria.Property), Expression.Constant(criteria.PropertyValue));
        LambdaExpression lambda = Expression.Lambda(property, parameter);

        Expression methodCallExpression = Expression.Call(typeof(Queryable), "SelectMany",
                                            new Type[] { source.ElementType, property.Type },
                                            source.Expression, Expression.Quote(lambda));

        return source.Provider.CreateQuery<T>(methodCallExpression);
    }
当我像这样从实体框架调用这个方法时

this.grdReservations.DataSource = dataContext.CustomerSet.SearchBy(crit);
这是搜索标准

        SearchCriteria crit = new SearchCriteria();
        crit.Property = "UserName";
        crit.PropertyValue = "new_user";
        crit.Search = SearchType.Equal;
如果有人能看一看,把我推向正确的方向,我会非常高兴

谢谢你抽出时间


编辑:我在家,所以我无法测试,但我尝试的任何方法(“选择”、“何处”、“选择多”)都返回了此错误,所以我假设我在做其他错误的事情

要调用SelectMany还是只选择


SelectMany需要一个lambda,它返回的是一个IEnumerable[TResult]而不是TResult。

lambda似乎接受类型为T的参数值并返回bool。看起来它应该返回一个IEnumerable

或者,如果将“SelectMany”更改为“Select”,lambda将需要返回类型为T的值

 this works

public static IQueryable<T> SearchBy<T>(this IQueryable<T> source, SearchCriteria criteria)
    {
        //throw an error if the source is null
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }

        ParameterExpression parameter = Expression.Parameter(source.ElementType, string.Empty);
        BinaryExpression property = Expression.Equal(Expression.PropertyOrField(parameter, criteria.Property), Expression.Constant(criteria.PropertyValue));
        LambdaExpression lambda = Expression.Lambda(property, parameter);

        Expression methodCallExpression = Expression.Call(typeof(Queryable), "Where",
                                            new Type[] { source.ElementType },
                                            source.Expression, Expression.Quote(lambda));

        return source.Provider.CreateQuery<T>(methodCallExpression);
    }
我帮了大忙


感谢您的时间,伙计们

都返回了相同的错误。事实上,我在其中输入的任何内容都会返回错误。您必须确保Expression.Call方法中最后一个参数的类型与作为第二个参数传递的方法所需的参数匹配。
 this works

public static IQueryable<T> SearchBy<T>(this IQueryable<T> source, SearchCriteria criteria)
    {
        //throw an error if the source is null
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }

        ParameterExpression parameter = Expression.Parameter(source.ElementType, string.Empty);
        BinaryExpression property = Expression.Equal(Expression.PropertyOrField(parameter, criteria.Property), Expression.Constant(criteria.PropertyValue));
        LambdaExpression lambda = Expression.Lambda(property, parameter);

        Expression methodCallExpression = Expression.Call(typeof(Queryable), "Where",
                                            new Type[] { source.ElementType },
                                            source.Expression, Expression.Quote(lambda));

        return source.Provider.CreateQuery<T>(methodCallExpression);
    }
new Type[] { source.ElementType }