Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dynamically build and return a linq predicate based on user input

Tags:

c#

.net

linq

Getting a bit stuck on this. Basically I have a method that I want to return a predicate expression that I can use as a Where condition. I think what I need to do is similar to this: http://msdn.microsoft.com/en-us/library/bb882637.aspx but I'm a bit stuck as to what I need to do.

Method:

private static Expression<Func<Conference, bool>> GetSearchPredicate(string keyword, int? venueId, string month, int year)
{
    if (!String.IsNullOrEmpty(keyword))
    {
        // Want the equivilent of .Where(x => (x.Title.Contains(keyword) || x.Description.Contains(keyword)));
    }
    if (venueId.HasValue) 
    {
        // Some other predicate added...
    }

    return ??

}

Example Usage:

var predicate = GetSearchPreducate(a,b,c,d);
var x = Conferences.All().Where(predicate);

I need this separation so that I can pass my predicate into my repository and use it in other places.

like image 566
Matt Roberts Avatar asked Oct 14 '10 11:10

Matt Roberts


2 Answers

A predicate is only a function that returns a boolean value.

I can not test it, right now, but wouldn't this work ?

private static Expression<Func<Conference, bool>> GetSearchPredicate(string keyword, int? venueId, string month, int year)
{
    if (!String.IsNullOrEmpty(keyword))
    {
        //return a filtering fonction
        return (conf)=> conf.Title.Contains(keyword) || Description.Contains(keyword)));
    }
    if (venueId.HasValue) 
    {
        // Some other predicate added...
        return (conf)=> /*something boolean here */;
    }

    //no matching predicate, just return a predicate that is always true, to list everything
    return (conf) => true;

}

EDIT : based on Matt's comments If you want to compose the delegates, you could proceed this way

private static Expression<Func<Conference, bool>> GetSearchPredicate(string keyword, int? venueId, string month, int year)
{   
    Expression<Func<Conference, bool> keywordPred = (conf) => true;
    Expression<Func<Conference, bool> venuePred = (conf) => true;
    //and so on ...


    if (!String.IsNullOrEmpty(keyword))
    {
        //edit the filtering fonction
        keywordPred =  (conf)=> conf.Title.Contains(keyword) || Description.Contains(keyword)));
    }
    if (venueId.HasValue) 
    {
        // Some other predicate added...
        venuePred =  (conf)=> /*something boolean here */;
    }

    //return a new predicate based on a combination of those predicates
    //I group it all with AND, but another method could use OR
    return (conf) => (keywordPred(conf) && venuePred(conf) /* and do on ...*/);

}
like image 177
tsimbalar Avatar answered Oct 14 '22 06:10

tsimbalar


Have you checked out PredicateBuilder

like image 25
Matthew Abbott Avatar answered Oct 14 '22 06:10

Matthew Abbott