Matthew The Terrible Matthew The Terrible - 2 months ago 14
C# Question

how can I make these methods generic?

What I have is some dictionaries that are all of the type

Dictionary<Guid, string>


I have a bunch of methods that basically do the same thing but use different parameters do filter various things. Here are a couple sample methods

private IQueryable<SomeClass> FilterContacts(Filter filter,
IQueryable<SomeClass> query)
{
if (filter.Contacts != null && filter.Contacts.Any())
{
result = result.Where(x => filter.Contacts.Contains(x.ContactID));
}

return result;
}

private IQueryable<SomeClass> FilterSomethingElse(Filter filter,
IQueryable<SomeClass> query)
{
if (filter.SomethingElse != null && filter.SomethingElse.Any())
{
result = result.Where(x => filter.SomethingElse.Contains(x.SomethingElseID));
}

return result;
}


So they all these methods share the same structure but use different properties on the filter and in the where clause. Is there a way to make this generic enough that I can just have one method that can do this?

Answer

The following solution uses a delegate as a parameter to inject some of the logic necessary to make the method more generic.

public IQueryable<SomeClass> FilterCommon(IQueryable<SomeClass> query
    , Filter filter
    , Func<Filter, Dictionary<Guid, string>> getDictionary
    , Func<SomeClass, Guid> getKey)
{
    IQueryable<SomeClass> result = null;
    Dictionary<Guid, string> commonDictionary = getDictionary(filter);
    if (commonDictionary != null && commonDictionary.Any())
    {
        result = query.Where(x => commonDictionary.ContainsKey(getKey(x)));
    }

    return result;
}

I don't think the Filter parameter is necessary so it can be simplified to this:

public IQueryable<SomeClass> FilterCommon(IQueryable<SomeClass> query
    , Dictionary<Guid, string> commonDictionary
    , Func<SomeClass,Guid> getKey)
{
    IQueryable<SomeClass> result = null;
    if (commonDictionary != null && commonDictionary.Any())
    {
        result = query.Where(x => commonDictionary.ContainsKey(getKey(x)));
    }

    return result;
}

Usage:

//Initializing a few things first...
Filter myFilter = new Filter();
IQueryable<SomeClass> query = new Queryable();//Just a generated type

//This is for my first example from above
FilterCommon(query, myFilter, x => x.Contacts, x => x.ContactID);

//Second example without filter parameter
FilterCommon(query, myFilter.Contacts, x => x.ContactID);
FilterCommon(query, myFilter.SomethingElse, x => x.SomethingElseID);