Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Linq where clause according to property name

Let's say I have the following class :

public class Person { 

    public string FirstName { get; set; }
    public string SurName { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }

}

Also, I have the following method and I am reaching out to person data via a repository.

public IEnumerable<Person> getPeople(string searchField, string searchTerm) { 

    //_repo.GetAll() returns IEnumerable<Person>
    var model = _repo.GetAll(); 

    //Need the logic here for filtering

    return model;
}

As you can see I am getting two parameter for the method : searchField and searchTerm.

searchField is for the field name whose value will be used for filtering. searchTerm is the value which will be used to compare with retrived value (sorry if I am not clear here but this is the most I can come up with)

What I would normally do is as follows :

public IEnumerable<Person> getPeople(string searchField, string searchTerm) { 

    //_repo.GetAll() returns IEnumerable<Person>
    var model = _repo.GetAll(); 

    switch(searchField) { 

        case "FirstName":
            model = model.Where(x => x.FirstName == searchTerm);
            break;

        case "SurName":
            model = model.Where(x => x.SurName == searchTerm);
            break;

        //Keeps going
    }

    return model;

}

Which will work just fine. But if I make a change on my class, this code will have a change to break or be in lack of some functions if I add new properties this class.

What I am looking for is something like below :

NOTE :

This below code completely belongs to my imagination and there is no such a thing exists.

model = model.Where(x => x.GetPropertyByName(searchField) == searchTerm);

Am I flying too high here if it is impossible or being complete idiot if there is already a built in way for this?

like image 335
tugberk Avatar asked Oct 11 '11 13:10

tugberk


2 Answers

Looks like you need Dynamic Linq queries:

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

like image 127
Jakub Konecki Avatar answered Sep 29 '22 11:09

Jakub Konecki


I use this extension method to achieve what you want.

public static IQueryable<TEntity> Where<TEntity>(this IQueryable<TEntity> source, string propertyName, string value) 
{

    Expression<Func<TEntity, bool>> whereExpression = x => x.GetType().InvokeMember(propertyName, BindingFlags.GetProperty, null, x, null).ObjectToString().IndexOf(value, StringComparison.InvariantCultureIgnoreCase) >= 0;

    return source.Where(whereExpression);       
}

Note: ObjectToString is just another extension method that returns string.Empty if the Object passed in is NULL

like image 34
Icarus Avatar answered Sep 29 '22 11:09

Icarus