Filtering an item from a list of items is easy but if the item to filter is not known at compile time then filtering a list will be little complicated.
Instead of writing dynamic filtering in C#, one might go for a
Stored Procedure and write a dynamic query based on the input column name and execute the dynamic SQL statement.
public class User
For the purpose of the article, we will have the following list of user data.
private static List<User> UserDataSeed()
Encapsulates a method that has one parameter and returns a value of the type specified by the TResult parameter. - from MSDN
For example, if we want to multiply two numbers, then with Func delegate we can write the following code
//Func will take two integers as arguments to multiply
Back to our original dynamic LINQ, we’ll use Func delegate to have dynamic LINQ queries.
If we want to get the specific ID of the user in a list of users then we will write the following LINQ on the list of users for different properties on the User model.
For filtering the ID property:
userData.Where(d => d.ID == val).ToList();
userData.Where(d => d.FirstName == val).ToList();
userData.Where(d => d.LastName == val).ToList();
From our console app, we will supply a
property name to filter on. So, can we have a switch statement to do this? (I know some of you don’t like the switch-case statement).
private static Func<User, bool> GetDynamicQueryWithFunc(string propName, object val)
In the above code snippet, we declared a Func delegate (exp) at the top and based on the property name we will assign the necessary lambda expression to the func delegate and return the delegate back to the caller.
Once we get the Func delegate from the method, we will apply that delegate on a list of user data.
var dynamicExpression = GetDynamicQueryWithFunc(propertyName, value);
var output = userData.Where(dynamicExpression).ToList();
I don’t like the above solution, although it solves the problem. Because, the code violates Open-Closed principle and the code use switch-case statement.
Let’s do the real dynamic LINQ querying with Expression trees.
An expression tree is a binary tree that will represent expressions. So, we have to build the expressions for the tree.
In C#, the expression trees concept is used to translate code into data.
With expression trees, we produce a data structure that represents your code.
Why do we need the expression trees now? We’ll use the expression trees to build our code as a data structure and we compile the expression tree to get a func delegate which can be used to filter the items.
Please read expresson trees from msdn
x => x.LastName == "Curry" in expression trees, we have to write the following code.
private static Func<User, bool> GetDynamicQueryWithExpresionTrees(string propertyName, string val)
In the above code we have the following line
var valExpression = Expression.Constant(val, typeof(string));
This makes the constant expression of type string but what if we give ID as the input to the program and run it. Well, it breaks with the following exception.
System.InvalidOperationException: ‘The binary operator Equal is not defined for the types ‘System.Int32’ and ‘System.String’.’
To fix this we have to get rid of that line and we will use the
TypeDescriptor to convert our value to the appropriate type.
As said, the following code will convert from a string to its own type of data.
var param = Expression.Parameter(typeof(User), "x");
var member = Expression.Property(param, propertyName);
var propertyType = ((PropertyInfo)member.Member).PropertyType;
var converter = TypeDescriptor.GetConverter(propertyType);
throw new NotSupportedException();
//will give the integer value if the string is integer
var propertyValue = converter.ConvertFromInvariantString(val);
var constant = Expression.Constant(propertyValue);
You can also use
int.TryParse to test if the string is an integer. If we chose this approach then we have to use if/else or switch-case statements to make that constant expression and also have to handle the value expression.
TypeDescriptor now in place let’s see the entire code.
static void Main(string args)
The above code blocks is a tabbed content check the second tab for the dynamic LINQ generation using Expression Trees.
Let’s try the code in dotnet fiddle and see it in action.
In the output window of the dotnet fiddle, try with ID property with the value within 1, 2, 3 or FirstName/LastName with the names “Kevin”/“Curry”.
Note that the following cases were not handled in the above code.
- Giving property names with spaces will cause the program to throw an exception as the property with names(ex: First name) is not in the User model.
- Providing a value that is not in the user seed data will cause the program to end without providing any result.
The source code of the above example snippets and demo in the dotnetfiddle is available on GitLab.
The old way of doing things dynamic is to write a stored procedure with a ton of IF statements and build a raw SQL query and then execute it at the end.
Instead of writing the dynamic SQL queries it is better to build the Expression Trees or Func
One might argue that we can filter a list of item dynamically with reflection, but reflection will be slow if the model class (in our case the
User class) has too many properties.