我有一个扩展方法,它创建一个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;
}