tek
tek

Reputation: 353

How to pass method on LINQ-generated object as delegate?

I have the following method (where SetTypes is an enum):

public IEnumerable<Chart> RetrieveCharts(IEnumerable<string> filters, SetTypes set)
{
    switch (set)
    {
        case SetTypes.Set: return GetChartsSet(filters);
        case SetTypes.Subset: return GetChartsSubset(filters);
        // Other cases here...
        default:
            throw new NotImplementedException();
    }
}

I am duplicating code across my method calls ... the only thing that's changing is the method call on the HashSet instance:

private IEnumerable<Chart> GetChartsSet(IEnumerable<string> filters)
{
    using (var db = new ChartContext())
    {
        return db.Charts.Where(c => new HashSet<string>(c.ProductFilters.Select(f => f.Filter)).SetEquals(filters)).Select(c => c);
    }
}

private IEnumerable<Chart> GetChartsSubset(IEnumerable<string> filters)
{
    using (var db = new ChartContext())
    {
        return db.Charts.Where(c => new HashSet<string>(c.ProductFilters.Select(f => f.Filter)).IsProperSubsetOf(filters)).Select(c => c);
    }
}
// More duplicated methods follow...

Instead of having multiple methods simply to call a different method on HashSet, I'd prefer a consolidated method which takes the HashSet method as an argument - but I'm not sure how to proceed. How do I do this?

Bonus points if you also tell me how to get rid of that switch statement. :)

Upvotes: 1

Views: 57

Answers (1)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726639

You could make a common implementation that takes an additional Predicate<HashSet<string>> on the set:

private IEnumerable<Chart> GetWithPredicate(Predicate<HashSet<string>> pred) {
    using (var db = new ChartContext()) {
        return db.Charts
            .Where(c => pred(new HashSet<string>(c.ProductFilters.Select(f => f.Filter))))
            .Select(c => c);
    }
}

and then reuse it in different methods:

private IEnumerable<Chart> GetChartsSet(IEnumerable<string> filters) {
    return GetWithPredicate(s => s.SetEquals(filters));
}

private IEnumerable<Chart> GetChartsSubset(IEnumerable<string> filters) {
    return GetWithPredicate(s => s.IsProperSubsetOf(filters));
}

Upvotes: 2

Related Questions