Как создать динамический метод расширения IQueryable - PullRequest
0 голосов
/ 08 апреля 2019
public static IQueryable<T> DynamicFilter<T>(this IQueryable<T> query, string Property, dynamic value) where T : class
{
    return query.Where(x => x.GetType().GetProperty(Property) == value).AsQueryable();
}

1 Ответ

1 голос
/ 08 апреля 2019

хитрость в том, чтобы посмотреть, что делает компилятор, то есть скомпилировать что-то вроде:

using System.Linq;

public class C {
    public void M() {
        var query = Data.Where(x => x.Bar == "abc");
    }
    System.Linq.IQueryable<Foo> Data;
    class Foo {
        public string Bar {get;set;}
    }
}

и посмотри, что он делает; если мы посмотрим в sharplab.io , то увидим:

public void M()
{
    IQueryable<Foo> data = Data;
    ParameterExpression parameterExpression = Expression.Parameter(typeof(Foo), "x");
    BinaryExpression body = Expression.Equal(Expression.Property(parameterExpression, (MethodInfo)MethodBase.GetMethodFromHandle((RuntimeMethodHandle)/*OpCode not supported: LdMemberToken*/)), Expression.Constant("abc", typeof(string)));
    ParameterExpression[] obj = new ParameterExpression[1];
    obj[0] = parameterExpression;
    IQueryable<Foo> queryable = Queryable.Where(data, Expression.Lambda<Func<Foo, bool>>(body, obj));
}

и мы можем сделать вывод, что вы хотите что-то подобное, т.е.

var p = Expression.Parameter(typeof(T), "x");
var body = Expression.Equal(
    Expression.PropertyOrField(p, Property),
    Expression.Constant((object)value)
);
var lambda = Expression.Lambda<Func<T, bool>>(body, p);
return query.Where(lambda);
...