如何将多个MethodCallExpressions连接到一个表达式?

时间:2017-01-19 11:10:44

标签: c# linq lambda expression

我有一个查询,我需要对其应用n个过滤器。但是我必须使用表达式。到目前为止,我已经为每个过滤器构建了表达式,这非常好。问题是我想将这些过滤器连接到一个表达式中,因此我可以将它用作LINQ的.Where()的参数。

过滤代码:

    //Filters could slightly differ in functionality 
    private Expression<Func<T, bool>> StringPropertyContains<T>(Filter filter)
    {
        if (filter == null)
        {
            throw new ArgumentNullException(nameof(filter));
        }

        if (typeof(T).GetProperties().FirstOrDefault(pi => pi.Name.Equals(filter.PropertyName, StringComparison.OrdinalIgnoreCase)) == null)
        {
            throw new ArgumentNullException($"Type {typeof(T)} does not contain property {filter.PropertyName}");
        }

        var propertyInfo = typeof(T).GetProperty(filter.PropertyName);
        var param = Expression.Parameter(typeof(T));
        var member = Expression.MakeMemberAccess(param, propertyInfo);
        var constant = Expression.Constant(filter.Value, typeof(filter.Type));
        var methodInfo = typeof(filter.Type).GetMethod(filter.Method, new Type[] { typeof(filter.Type) });
        var body = Expression.Call(member, methodInfo, constant);

        return Expression.Lambda<Func<T, bool>>(body, param);
    }

    private Expression<Func<T, bool>> Filter<T>(T t)
    {
        //TODO join filters while each filter should have its different parameter
        //the parameter is currently constructed in the object and is accessible via property Filter[] ParsedFilter
    }

过滤类:

internal class Filter
{
    public string Type { get; }
    public string Method { get; }
    public string PropertyName { get; }
    public string Value { get; }
}

所需用法:

IQueryable<T> q = query.Where(this.Filter)

老实说,我对这个问题非常头疼,因为我对表达方式很陌生。所以感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您不能将类作为参数传递给Where子句,但是您可以使用Linq表达式来实现您想要的内容:

Expression<Func<T, bool>> filter = q => q.type == filter.Type && q.Value == filter.Value;

var x = query.Where(filter);