Reputation: 291
I have a extension method which creates a lambda predicate expression, which I use to filter data when the value is not null
.
It works fine for cases like
query.FilterBy(obj => obj.MyProp, value);
but it fails in cases like
query.FilterBy(obj => obj.MyObject.MyProp, value);
In this case the expression for MyProp
property is accessed on obj
, which of course doesn't have the property.
I'm not familiar with the expression tree and could not figure out how to modify the extension method to access properties of sub objects. Does anyone have an idea how I could do it?
The extension method:
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;
}
Upvotes: 0
Views: 657
Reputation: 106
You could simply use epxression passed like parameter property of FilterBy() function for creating new filtering expression instead of trying to create expression from scratch. It will works with "sub-properties".
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;
}
Upvotes: 1