using System.Collections.Generic;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;
public static void Main()
Can_use_custom_expression();
public static void Can_use_custom_expression()
var dbContext = new ApplicationDbContext();
dbContext.Users.Add(new ApplicationUser { FirstName = "Foo", LastName = "Bar" });
Expression<Func<string, string, bool>> valueCheck = (value, expected) => !string.IsNullOrEmpty(value) && value.Contains(expected);
var valueCheckFunc = valueCheck.Compile();
Expression<Func<ApplicationUser, bool>> whereExpression = (u) => valueCheckFunc(u.FirstName, query);
whereExpression = whereExpression.Replace(() => valueCheckFunc, valueCheck);
var user = dbContext.Users
Console.WriteLine(user != null ? $"Found {user.FirstName} {user.LastName}!" : "User not found!");
public static class DelegateByLambdaExtensions
public static Expression<T> Replace<T, X>(this Expression<T> source, Expression<Func<X>> delegateReference, Expression<X> lambdaReference)
return new DelegateByLambda(delegateReference, lambdaReference).Visit(source) as Expression<T>;
public class DelegateByLambda: ExpressionVisitor
LambdaExpression delegateReferenceExpression;
LambdaExpression lambdaExpression;
Stack<InvocationExpression> invocations;
public DelegateByLambda(LambdaExpression delegateReferenceExpression, LambdaExpression lambdaExpression)
this.delegateReferenceExpression = delegateReferenceExpression;
this.lambdaExpression = lambdaExpression;
this.invocations = new Stack<InvocationExpression>();
protected override Expression VisitParameter(ParameterExpression node)
var paramIndex = lambdaExpression.Parameters.IndexOf(node);
InvocationExpression call = invocations.Peek();
return base.Visit(call.Arguments[paramIndex]);
return base.VisitParameter(node);
protected override Expression VisitInvocation(InvocationExpression node)
if (node.Expression.ToString() == delegateReferenceExpression.Body.ToString())
var result = base.Visit(lambdaExpression.Body);
return base.VisitInvocation(node);
public class ApplicationUser
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public class ApplicationDbContext : DbContext
public ApplicationDbContext() : base()
public ApplicationDbContext(DbContextOptions options) : base(options)
public DbSet<ApplicationUser> Users { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseInMemoryDatabase("Test");