-1
public class Person
{
    public int Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public int? Age { get; set; }
}

var persons = new List<Person>
{
    new Person { Id = 1, FirstName = "Fox", LastName = "Mulder", Age = 40 },
    new Person { Id = 2, FirstName = "Dana", LastName = "Scully", Age = 35 }
};

List<Person> Search(List<Person> persons, Person person)
{

    //Here I'd like create a predicate here it's a AND between each.

    //If !string.IsNullOrEmpty(person.FirstName) add to predicate, same for LastName

    //If  person.Age.HasValue() add to predicate

    return persons.Where(myPredicateHere);
}

As explained in the Search method I'd like combine with a AND, if FirstName is not null or empty it's part of the predicate, same for LastName and if the Age has a value add it to the predicate.

Any idea ?

Thanks,

TheBoubou
  • 19,487
  • 54
  • 148
  • 236
  • Does this answer your question? [How does PredicateBuilder work](https://stackoverflow.com/questions/11490893/how-does-predicatebuilder-work) – Franck Nov 08 '22 at 12:23
  • I think you want a dynamic where clause. – GH DevOps Nov 08 '22 at 12:27
  • @Franck on this isAdult.And(isMale) '.And' is unknow – TheBoubou Nov 08 '22 at 12:28
  • @Kris-I doesn't matter the condition is known at one point. You can build it with reflection if you want. The return is an expression and it's additive. If you have 10 conditions `And` you keep doing `mainExpression = mainExpression.And(newExpression)` and they will pipe behind each other – Franck Nov 08 '22 at 12:49

2 Answers2

0

Something like that?

List<Person> Search(List<Person> persons, Person person)
        {
            Func<Person, bool> predicate = x => x.Id == person.Id;

            if (!string.IsNullOrEmpty(person.FirstName))
            {
                predicate = x => !string.IsNullOrEmpty(person.FirstName) && x.Id == person.Id;
            }

            if (!string.IsNullOrEmpty(person.LastName))
            {
                predicate = x => !string.IsNullOrEmpty(person.LastName) && x.Id == person.Id;
            }

            if (person.Age.HasValue)
            {
                predicate = x => person.Age.HasValue && x.Id == person.Id;
            }

            return persons.Where(predicate).ToList();
        }
Viachaslau S
  • 106
  • 1
  • 5
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Nov 11 '22 at 00:45
0

Another option apart from build up a dynamic predicate, is to chain Where calls

List<Person> Search(List<Person> persons, Person person)
{

    IEnumerable<Person> result = persons;
    if(!String.IsNullOrEmpty(person.FirstName))
    {
        result = result.Where(x => x.FirstName == person.FirstName);
    }
    if(!String.IsNullOrEmpty(person.LastName))
    {
        result = result.Where(x => x.LastName == person.LastName);
    }
    if(person.Age.HasValue)
    {
        result = result.Where(x => x.Age == person.Age);
    }
    return result.ToList();
}

Live example: https://dotnetfiddle.net/Xs4x8V

Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • 1
    I think you would need `var result = persons.AsEnumerable();` or something similar, seeing as `persons` is a list – Astrid E. Nov 08 '22 at 13:02
  • @AstridE. no, `List` is `IEnumerable` - and thats where `Where` lives. – Jamiec Nov 08 '22 at 16:14
  • The problem with the current implementation (with `result` being a `List`) is when you assign `result = result.Where(...)`, because it is not cast to a list. Does your code compile for you? – Astrid E. Nov 08 '22 at 17:16
  • @AstridE. I typed it out in a hurry, but you're (sort of) right - you need to actually be explicit about `result` being `IEnumerable` - see update and linked live example. – Jamiec Nov 08 '22 at 17:32
  • Yes, both approaches result in `result` being an `IEnumerable` rather than a `List`. Needing to be explicit about `result` being an `IEnumerable` was indeed the main point of my first comment; my bad for not actually stating that. – Astrid E. Nov 08 '22 at 18:52