I'm trying to create a dynamic filter for various classes. We would only know at runtime what type we're dealing with. I need the ColumnName to be the actual column (not a string value).
Is there an easy way to convert the string into a column?
public static List<T> Filter<T>
(this List<T> Source, string ColumnName,
string TypeOfCompare, string CompValue)
{
IQueryable<T> matches = Source.AsQueryable();
if (ColumnName.Length > 0)
{
matches = (IEnumerable)matches.Where(a => ColumnName == CompValue)
}
List<T> ReturnList2 = new List<T>();
ReturnList2 = matches.ToList();
return ReturnList2;
}
If you want to create dynamic list name, you can try to below code, create Dictionary<string, List<string>>. var dict = new Dictionary<string, List<string>>(); dict["x1"] = new List<string>(); You can replace "x1" with variable.
You can use a dynamic object to refer to a dynamic script that is interpreted at run time. You reference a dynamic object by using late binding. In C#, you specify the type of a late-bound object as dynamic . In Visual Basic, you specify the type of a late-bound object as Object .
And lists are also dynamic, meaning that you can add elements to the list or remove elements from a list completely. So the list can grow or shrink depending on how you use it.
Dynamic types are similar to object types except that type checking for object type variables takes place at compile time, whereas that for the dynamic type variables takes place at runtime.
Basically you need to build an expression tree. It's not terribly hard, fortunately, using Expression.Property
. You can either pass that to Queryable.Where
, or compile it and pass it to Enumerable.Where
. (Obviously you'll need to use something like Expression.Equal
as well, depending on the type of comparison you're trying to make.)
Is CompValue
meant to be an actual value? What's TypeOfCompare
meant to be?
I'm not sure where LINQ to Entities fits into this, either... you're only using LINQ to Objects really, as far as I can see.
EDIT: Okay, here's a sample. It assumes you want equality, but it does what you want if so. I don't know what the performance impact of compiling an expression tree every time is - you may want to cache the delegate for any given name/value combination:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
static class Extensions
{
public static List<T> Filter<T>
(this List<T> source, string columnName,
string compValue)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "x");
Expression property = Expression.Property(parameter, columnName);
Expression constant = Expression.Constant(compValue);
Expression equality = Expression.Equal(property, constant);
Expression<Func<T, bool>> predicate =
Expression.Lambda<Func<T, bool>>(equality, parameter);
Func<T, bool> compiled = predicate.Compile();
return source.Where(compiled).ToList();
}
}
class Test
{
static void Main()
{
var people = new[] {
new { FirstName = "John", LastName = "Smith" },
new { FirstName = "John", LastName = "Noakes" },
new { FirstName = "Linda", LastName = "Smith" },
new { FirstName = "Richard", LastName = "Smith" },
new { FirstName = "Richard", LastName = "Littlejohn" },
}.ToList();
foreach (var person in people.Filter("LastName", "Smith"))
{
Console.WriteLine(person);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With