Замена ответа после уточнения в комментариях:
Для последовательного создания дополнительных фильтров вам не нужны деревья выражений; Вы можете звонить .Where
несколько раз (при необходимости, один раз для каждого поискового запроса) - например:
IEnumerable<DataRow> query = tempResults.AsEnumerable();
if(!string.IsNullOrEmpty(value1)) {
query = query.Where(row => row.Field<string>("Col1") == value1);
}
if (!string.IsNullOrEmpty(value2)) {
query = query.Where(row => row.Field<string>("Col2") == value2);
}
Единственное, что нужно посмотреть, это проблема «захвата»; не используйте повторно ни один из value1
, value2
и т. д., иначе последнее значение будет применяться к более ранним фильтрам ...
Для примера комбинации делегатов (из комментариев) - обратите внимание, что здесь я упустил аспект DataTable
исключительно для того, чтобы сделать пример короче (он будет работать идентично):
public static class Predicate {
public static Func<T, bool> OrElse<T>(
this Func<T, bool> lhs, Func<T, bool> rhs) {
return lhs == null ? rhs : obj => lhs(obj) || rhs(obj);
}
public static Func<T, bool> AndAlso<T>(
this Func<T, bool> lhs, Func<T, bool> rhs) {
return lhs == null ? rhs : obj => lhs(obj) && rhs(obj);
}
}
class Data {
public string Color { get; set; }
}
class Program {
static void Main() {
bool redChecked = true, greenChecked = true; // from UI...
List<Data> list = new List<Data>() {
new Data { Color = "red"},
new Data { Color = "blue"},
new Data { Color = "green"},
};
Func<Data, bool> filter = null;
if (redChecked) {
filter = filter.OrElse(row => row.Color == "red");
}
if (greenChecked) {
filter = filter.OrElse(row => row.Color == "green");
}
if (filter == null) filter = x => true; // wildcard
var qry = list.Where(filter);
foreach (var row in qry) {
Console.WriteLine(row.Color);
}
}
}
(оригинальный ответ)
На самом деле, этот вариант LINQ не будет использовать дерево выражений ... он будет использовать делегат; но вы можете построить дерево и скомпилировать его, если вы действительно хотите ... Я не уверен, почему вы это сделаете. Что ты хочешь делать? Я приведу пример ...
Вот, пожалуйста; здесь используется дерево выражений, но я не могу придумать ни одной веской причины для этого, кроме как доказать, что вы можете!
public static class MyExtensions
{
public static IQueryable<TRow> Where<TRow, TValue>(
this IQueryable<TRow> rows,
string columnName, TValue value)
where TRow : DataRow
{
var param = Expression.Parameter(typeof(TRow), "row");
var fieldMethod = (from method in typeof(DataRowExtensions).GetMethods()
where method.Name == "Field"
&& method.IsGenericMethod
let args = method.GetParameters()
where args.Length == 2
&& args[1].ParameterType == typeof(string)
select method)
.Single()
.MakeGenericMethod(typeof(TValue));
var body = Expression.Equal(
Expression.Call(null,fieldMethod,
param,
Expression.Constant(columnName, typeof(string))),
Expression.Constant(value, typeof(TValue))
);
var lambda = Expression.Lambda<Func<TRow, bool>>(body, param);
return rows.Where(lambda);
}
}
class Program
{
static void Main(string[] args)
{
DataTable tempResults = new DataTable();
tempResults.Columns.Add("ColumnName");
tempResults.Rows.Add("foo");
tempResults.Rows.Add("Column");
var test = tempResults.AsEnumerable().AsQueryable()
.Where("ColumnName", "Column");
Console.WriteLine(test.Count());
}
}