TruMan1
TruMan1

Reputation: 36178

How to pass a Linq staement for another type?

Below I have a method that wraps another method. What I'd like to do is provide an optional parameter to filter the inner method, which is a different type than T.

This is the outside method that is considered the "public" API:

public override IQueryable<T> GetEverything()
{
    return Get()
        .Where(i => i.Active == true)
        .Select(i => new T(i));
}

As pseudo code, I would like do something like this:

var items = GetEverything(x => x.SomeValue > 10);

Which would get passed into the method like this

   public override IQueryable<T> GetEverything(???)
    {
        return Get()
            .Where(i => i.Active == true)
            .Where(x => x.SomeValue > 10)
            .Select(i => new T(i));
    }

Notice I still want to keep my i.Active filter and don't want to loose that if the dev decides to pass in a filter. The passed in filter would compound not replace the inner filter. Can anyone help with this? Any help or advice would be greatly appreciated!

Upvotes: 0

Views: 81

Answers (1)

D Stanley
D Stanley

Reputation: 152654

Just look at the signature of Queryable.Where:

public static IQueryable<TSource> Where<TSource>(
    this IQueryable<TSource> source,
    Expression<Func<TSource, bool>> predicate
)

so in order to pass the parameter to Where the simplest way is to require a Expression<Func<TSource, bool>>:

public override IQueryable<T> GetEverything(Expression<Func<T, bool>> predicate)
{
    return Get()
        .Where(i => i.Active == true)
        .Where(predicate)
        .Select(i => new T(i));
}

Be aware that most query providers have limitations on what expressions can be converted to an underlying store query, so you may run into more run-time errors by providing an open door to the filters.

If you want to keep a single method and allow a null predicate you could just chaine the Linq expressions:

public override IQueryable<T> GetEverything(Expression<Func<T, bool>> predicate = null)
{
    var query = Get().Where(i => i.Active == true);

    if(predicate != null)
        query = query.Where(predicate);

    return query.Select(i => new T(i));
}

Upvotes: 5

Related Questions