Dynamic location for list <T>
I am trying to create a dynamic filter for various classes. We only know at runtime what type we are dealing with. I need the column to be an actual column (not a string column).
Is there an easy way to convert a row to 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; } Basically, you need to build an expression tree. Unfortunately, this is not very difficult using Expression.Property . You can either pass this to Queryable.Where or compile it and pass it to Enumerable.Where . (Obviously, you need to use something like Expression.Equal as well depending on the type of comparison you are trying to do.)
Is CompValue actual value? What TypeOfCompare mean?
I'm not sure where LINQ to Entities fits into this, either ... you are apparently using LINQ for objects as far as I know.
EDIT: Alright, here is a sample. He assumes that you want equality, but he does what you want, if so. I donβt know what the performance impact on the assembly of the expression tree is every time - you may want to cache the delegate for any combination of names / values:
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); } } } Instead of the ColumnName string ColumnName you cannot pass a selector for this column (I understand that this is not always possible, but just in case it is ...)? That you could use.
By the way, the code is too complicated. This should work:
public static List<T> Filter<T>( this List<T> Source, Func<T, string> selector, string CompValue) { return Source.Where(a => selector(a) == CompValue).ToList(); } Then you can call the code as follows:
var result = myList.Filter(x => x.ColumnName, "foo"); You are looking for something like this: http://naspinski.net/post/Writing-Dynamic-Linq-Queries-in-Linq-to-Entities.aspx Otherwise, you must handle each case separately, as in the following:
if (columnName == "blah") matches = matches.Where(i => i.Blah == Value); if (columnName == "name") matches = matches.Where(i => i.Name == Value);