using System.Linq.Expressions;
using System.Collections.Generic;
public class FilterParamsDto
public int? StudentId { get; set; }
public int? NationalityId { get; set; }
public int? CountryId { get; set; }
public int? SchoolCountryId { get; set; }
public int? SchoolStateId { get; set; }
public int? SchoolCityId { get; set; }
public int StudentId { get; set; }
public int NationalityId { get; set; }
public int CountryId { get; set; }
public int SchoolCountryId { get; set; }
public int SchoolStateId { get; set; }
public int SchoolCityId { get; set; }
public static class Program
public static void Main()
var dto = new FilterParamsDto { CountryId = 3, StudentId = 5 };
var data = new List<Dummy> { new() { CountryId = 3, StudentId = 1 }, new() { CountryId = 4, StudentId = 5 }, new() { CountryId = 1, StudentId = 2 }, new() { CountryId = 3, StudentId = 5 } };
var expAnd = GenerateFilterExpression<Dummy, FilterParamsDto>(dto);
var expOr = GenerateFilterExpression<Dummy, FilterParamsDto>(dto, false);
var filteredWithAnd = data.AsQueryable().Where(expAnd).ToArray();
var filteredWithOr = data.AsQueryable().Where(expOr).ToArray();
public static PropertyInfo[] GetNonNullProperties<T>(T item) where T : class
var properties = typeof(T)
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(r => r.GetValue(item) != null)
.Select(r => r).ToArray();
public static Expression<Func<T, bool>> GenerateFilterExpression<T, R>(R dto, bool and = true) where T : class where R : class
var p = Expression.Parameter(typeof(T), "p");
var nonnullProps = GetNonNullProperties(dto);
var constExp = Expression.Constant(dto);
Func<Expression, Expression, BinaryExpression> operatorExp = and ? Expression.AndAlso : Expression.OrElse;
var sourceType = typeof(T);
foreach (var item in nonnullProps)
var sourceProp = sourceType.GetProperty(item.Name);
var prop = Expression.Property(p, sourceProp!);
Expression dtoProp = Expression.Property(constExp, item);
if (sourceProp!.PropertyType != item.PropertyType)
var underlyingType = Nullable.GetUnderlyingType(item.PropertyType);
dtoProp = Expression.Convert(dtoProp, underlyingType!);
exp = Expression.Equal(prop, dtoProp);
exp = operatorExp(exp, Expression.Equal(prop, dtoProp));
var result = Expression.Lambda<Func<T, bool>>(exp!, p);