Dylan Parry
Dylan Parry

Reputation: 3453

Repository method accepting predicate and orderby

I’ve set up a repository with Entity Framework and have the following interface method:

Task<IList<Person>> SearchForPeople(Expression<Func<Person, bool>> predicate, Expression<Func<Person, object>> orderBy);

It’s fairly basic, and I’ve implemented it as:

public async Task<IList<Person>> SearchForPeople(Expression<Func<Person, bool>> predicate, Expression<Func<Person, object>> orderBy)
{
    return await this.context.People.Where(predicate).OrderBy(orderBy).ToListAsync();
}

I’m currently calling it like this:

var people = await repository.SearchForPeople(x => x.Born.Day == now.Day && x.Born.Month == now.Month, x => x.OrderingKey);

Which returns all the people whose birthdays fall on the specified day/month, and then orders them according to a property called "orderingKey" which is essentially their name concatenated.

This works fine, but if I try to change the orderby to something like this:

var people = await repository.SearchForPeople(x => x.Born.Day == now.Day && x.Born.Month == now.Month, x => x.Born);

I get an error saying that I cannot cast System.DateTime to System.Object. I understand why this is happening as I’ve clearly stated that the orderby property should be of type “object”, but I cannot see how to rewrite this so that my orderby accepts any type of property to orderby without rewriting the whole thing using the generic T, which I don’t really want to do as I don’t want a generic repository just a generic filter!

Is there another way of making both types of orderby work?

Upvotes: 4

Views: 7557

Answers (2)

Daniel Bj&#246;rk
Daniel Bj&#246;rk

Reputation: 2507

Try this:

public async Task<IList<Person>> SearchForPeople<TOrderKey>(Expression<Func<Person, bool>> predicate, Expression<Func<Person, TOrderKey>> orderBy)
{
    return await this.context.People.Where(predicate).OrderBy(orderBy).ToListAsync();
}

Instead of passing in "Object" you define it as a generic parameter.

Upvotes: 1

CodingIntrigue
CodingIntrigue

Reputation: 78605

You can make just that method generic:

public async Task<IList<Person>> SearchForPeople<T>(Expression<Func<Person, bool>> predicate, Expression<Func<Person, T>> orderBy)
{
    return await this.context.People.Where(predicate).OrderBy(orderBy).ToListAsync();
}

Then using type inference, the following should work:

var people = await repository.SearchForPeople(x => x.Born.Day == now.Day && x.Born.Month == now.Month, x => x.Born);

Upvotes: 6

Related Questions