I have the following method which builds an expression based on a column name and value:
public Func<TSource, bool> SimpleComparison<TSource>(string property, object value)
{
var type = typeof (TSource);
var pe = Expression.Parameter(type, "p");
var propertyReference = Expression.Property(pe, property);
var constantReference = Expression.Constant(value);
return Expression.Lambda<Func<TSource, bool>>
(Expression.Equal(propertyReference, constantReference),
new[] { pe }).Compile();
}
I am trying to create a list of expressions, then query my datasource with the final concatenated/compiled expression.
I have tried to use Expression.Block
but the concept is a bit difficult for me to grasp. I have also seen Expression.Loop
but am not sure if it's what I need to use here.
Ideally, I would be able to do something like this:
var filters = request.Filter.Filters;
IQueryable<MyDTO> myDataSource = context.MyDataSource;
var expressions = null;
foreach (var filter in filters)
{
expressions.Add(SimpleExpression<MyDTO>(filter.Name, filter.Value));
}
return myDataSource.Where(expressions);
Any ideas on how to do something like this?
You're over-thinking things. You don't need to combine your expressions at all. The only complicated part is implementing SimpleComparison
, but you've done that already. Well, mostly. You should be returning Expression<Func<...>>
, not Func<...>
, so it should be
public Expression<Func<TSource, bool>> SimpleComparison<TSource>(string property, object value)
{
// ...
return Expression.Lambda<Func<TSource, bool>>
(Expression.Equal(propertyReference, constantReference),
new[] { pe });
}
Once you have that, you can chain the filters by calling Where
repeatedly, like so:
var filters = request.Filter.Filters;
IQueryable<MyDTO> query = context.MyDataSource;
foreach (var filter in filters)
query = query.Where(SimpleComparison<MyDTO>(filter.Name, filter.Value));
return query;