创建 lambda 谓词表达式以访问对象子属性



我有一个扩展方法,它创建一个lambda谓词表达式,当值未null时,我用它来过滤数据。

它适用于以下情况

query.FilterBy(obj => obj.MyProp, value);

但它在以下情况下失败

query.FilterBy(obj => obj.MyObject.MyProp, value);

在这种情况下,MyProp属性的表达式是在obj上访问的,当然没有属性。

我不熟悉表达式树,无法弄清楚如何修改扩展方法来访问子对象的属性。有人知道我该怎么做吗?

扩展方法:

public static IQueryable<TSource> FilterBy<TSource, TProp>(this IQueryable<TSource> source,
Expression<Func<TSource, TProp>> property,
TProp value)
{
if (value != null)
{
var parameter = Expression.Parameter(typeof(TSource));
var memberExpression = property.Body as MemberExpression ??
((UnaryExpression)property.Body).Operand as MemberExpression;
if (memberExpression is null)
{
throw new InvalidOperationException("Please provide a valid property expression.");
}
var propertyName = memberExpression.Member.Name;
var body = Expression.Equal(
Expression.Property(parameter, propertyName),
Expression.Constant(value));
var predicate = Expression.Lambda<Func<TSource, bool>>(body, parameter);
source = source.Where(predicate);
}
return source;
}

您可以简单地使用 epxression 传递,例如 FilterBy() 函数的参数属性来创建新的过滤表达式,而不是尝试从头开始创建表达式。它将与"子属性"一起使用。

public static IQueryable<TSource> FilterBy<TSource, TProp>(this IQueryable<TSource> source,
Expression<Func<TSource, TProp>> property,
TProp value)
{
if (value != null)
{
var expression = Expression.Equal(property.Body, Expression.Constant(value));
var predicate = Expression.Lambda<Func<TSource, bool>>(expression, property.Parameters[0]);
source = source.Where(predicate);
return source;
}
return source;
}

最新更新