views:

90

answers:

3

I am working on this mvc project following Rob Connery's storefront video series and applying the techniques. On the filtering and extensions methods, i started repeating myself a lot such as:

public static Sponsor WithID(this IQueryable<Sponsor>qry, int ID)
{
    return qry.SingleOrDefault(s => s.ID== ID);
}

public static Keyword WithID(this IQueryable<Keyword>qry,int ID)
{
    return qry.SingleOrDefault(s => s.ID== ID);
}
....

To prevent this,I try to write a generic extension like this:

public static T WithID<T>(this IQueryable<T>qry,int ID)
{
    return qry.SingleOrDefault(s=>ID==ID);
}

however s does not have ID, so how would you solve this?

+5  A: 

You'll need an interface which declares an ID property, e.g.

public interface IInt32Identifiable
{
    public int ID { get; }
}

Then you can write:

public static T WithID<T>(this IQueryable<T> source, int id)
    where T : IInt32Identifiable
{
   return source.SingleOrDefault(s=> s.ID == id);
}

Of course, you'll have to make all the appropriate classes implement the interface - but that's usually easy; if the classes are designer-generated you probably want to use partial classes.

Jon Skeet
A: 

You would need two different extension methods. One for types that have an ID and one for types that don't. You'd also need an interface or abstract base class that all ID'd types implement. Otherwise, the compiler won't let you dereference ID.

The only other alternative that I can think of would require reflection to query the type for the ID property, and if it exists, get the value.

Jeff Yates
A: 

You could also pass in the delegate to SingleOrDefault

 public static T WithID<T>(this IQueryable<T> qry, Func<T, bool> predicate)
 {
  return qry.SingleOrDefault(predicate);
 }

 Keyword kw = keywords.AsQueryable().WithID(item => item.ID == 314);
Dan