Ersetzte Antwort nach Klärung in den Kommentaren:
Für den sukzessiven Aufbau weiterer Filter benötigen Sie keine Ausdrucksbäume; Sie können die .Where
mehrmals (je nach Bedarf, einmal pro Suchbegriff) - zum Beispiel:
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);
}
Das Einzige, worauf Sie achten müssen, ist die Frage des "Capture"; stellen Sie sicher, dass Sie keine der Dateien wiederverwenden. value1
, value2
usw. - andernfalls gilt der letzte Wert für früher Filter...
Für ein Beispiel einer Delegatenkombination (aus Kommentaren) - beachten Sie, dass ich die DataTable
Aspekt hier nur, um das Beispiel kürzer zu machen (es funktioniert identisch):
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);
}
}
}
(Originalantwort)
Eigentlich wird diese Variante von LINQ keinen Ausdrucksbaum verwenden... es wird einen Delegaten verwenden; aber Sie können den Baum erstellen und kompilieren, wenn Sie wirklich wollen... Ich bin mir allerdings nicht sicher, warum Sie das tun sollten. Was wollen Sie tun? Ich werde ein Beispiel erstellen...
Hier ist es; dies verwendet einen Ausdrucksbaum, aber mir fällt kein einziger guter Grund ein, dies zu tun, außer um zu beweisen, dass man es kann!
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());
}
}