I have 2 lambda expressions that are virtually the same. One returns Expression<Func<Person, bool>>
and the other returns Expression<Func<Admission, bool>>
.
There is a direct relationship between these 2 entities. A Person
can have many Admissions
.
The two expressions look like this:
Person expression:
public static Expression<Func<Person, bool>> SearchPerson(string searchTerm)
{
if(string.IsNullOrEmpty(searchTerm))
{
return p => true;
}
return p => p.Nhino.Contains(searchTerm) ||
p.Firstname.Contains(searchTerm) ||
p.Lastname.Contains(searchTerm) ||
p.Pfname.Contains(searchTerm);
}
Admission expression:
public static Expression<Func<Admission, bool>> SearchPerson(string searchTerm)
{
if(string.IsNullOrEmpty(searchTerm))
{
return a => true;
}
return a => a.Person.Nhino.Contains(searchTerm) ||
a.Person.Firstname.Contains(searchTerm) ||
a.Person.Lastname.Contains(searchTerm) ||
a.Person.Pfname.Contains(searchTerm);
}
These search expressions are used extensively throughout the system.
Notice that the return
statements are virtually identical, and if our client wants to add more search criteria to the list I want to have this logic in one place and not have to update it for both the Admission
and Person
expressions.
Is there a way to create an expression or similar that can be used in both the People.Where()
clause and the Admissions.Where()
clause (or even other Parent/Child relationships that want to search by the same Person
criteria) without duplicating code?
Provided that you have control over the design of these classes, you can implement an interface with a predicate function.
For example:
public interface ITestable
{
Func<string, bool> Predicate { get; }
}
public class Admission : ITestable
{
// ...other members...
public Person Person { get; }
public Expression<Func<string, bool>> Predicate =>
x => Person.Predicate(x);
}
public class Person : ITestable
{
// ...other members...
public Expression<Func<string, bool>> Predicate =>
x => string.IsNullOrEmpty(x) || FirstName.Contains(x) || LastName.Contains(x);
}
// The calling code:
IQueryable<ITestable> people =
source.Where(x => x.Predicate(searchTerm));