动态 Where 过滤器通过导航属性

SO *_*ood 2 c# linq entity-framework-core

我正在创建一个通用的 Where 过滤器,到目前为止效果很好(只对Contains过滤器感兴趣):

private static MethodInfo contains = typeof(string).GetMethod("Contains");
private static Expression<Func<T, bool>> GetFilter<T>(string propertyName, string value)
{
    var item = Expression.Parameter(typeof(T), "item");
    var member = Expression.Property(item, propertyName);
    var constant = Expression.Constant(value);
    var body = Expression.Call(member, contains, constant);

    return Expression.Lambda<Func<T, bool>>(body, item);
}
Run Code Online (Sandbox Code Playgroud)

有什么方法可以扩展它以便我可以通过导航属性进行搜索?我对使用很陌生,Expression所以我不确定要尝试什么。

一个例子是:

public class A
{
    public int BId { get; set; }
    public B B { get; set; }
}

public class B
{
    public string Name { get; set; }
}

dbContext.As
    .Where(GetFilter<A>("B.Name", "Hello World"))
    .ToList();
Run Code Online (Sandbox Code Playgroud)

但这失败Expression.Property("B.Name")了:

B.Name未为类型定义实例属性A

Tit*_*mir 5

您需要为属性路径中的每个属性依次创建每个成员访问权限:

private static Expression<Func<T, bool>> GetFilter<T>(string propertyName, string value)
{
    var item = Expression.Parameter(typeof(T), "item");

    Expression member = item;
    foreach (var prop in propertyName.Split('.'))
    {
        member = Expression.Property(member, prop);
    }

    var constant = Expression.Constant(value);
    var body = Expression.Call(member, contains, constant);

    return Expression.Lambda<Func<T, bool>>(body, item);
}
Run Code Online (Sandbox Code Playgroud)