2008-09-17 8 views
6

Inspiré par la vitrine MVC, le dernier projet sur lequel je travaille utilise des méthodes d'extension sur IQueryable pour filtrer les résultats.Les méthodes d'extension ne fonctionnent pas pour une interface

J'ai cette interface;

IPrimaryKey 
{ 
    int ID { get; } 
} 

et moi avons cette méthode d'extension

public static IPrimaryKey GetByID(this IQueryable<IPrimaryKey> source, int id) 
{ 
    return source(obj => obj.ID == id); 
} 

Disons que j'ai une classe, SimpleObj qui implémente IPrimaryKey. Lorsque j'ai un IQueryable de SimpleObj la méthode GetByID n'existe pas, à moins que j'exécute explicitement comme IQueryable de IPrimaryKey, ce qui n'est pas idéal.

Ai-je oublié quelque chose ici?

Répondre

13

Il fonctionne , quand c'est bien fait. La solution de cfeduke fonctionne. Cependant, vous ne devez pas faire générique l'interface IPrimaryKey, en fait, vous ne devez pas changer votre définition originale du tout:

public static IPrimaryKey GetByID<T>(this IQueryable<T> source, int id) where T : IPrimaryKey 
{ 
    return source(obj => obj.ID == id); 
} 
+0

Excellent - J'ai unaccepted la réponse originale. Je vais essayer ça demain. Merci à vous deux. – Kirschstein

+1

Je voudrais juste dire que ma réponse n'était pas fausse, c'était la raison pour laquelle son code ne fonctionnait pas, je n'ai juste pas pris le temps de trouver une solution. Up a voté votre meilleure réponse. –

+0

Juste un point très mineur: il faut GetByID (ce IQueryable source ... – Kirschstein

2

Cela ne peut pas fonctionner en raison du fait que les génériques n'ont pas la capacité de suivre les modèles d'héritage. c'est à dire. IQueryable <SimpleObj> est pas dans l'arbre d'héritage de IQueryable <IPrimaryKey>

4

Edit: solution de Konrad est mieux parce que son beaucoup plus simple. La solution ci-dessous fonctionne mais n'est requise que dans des situations similaires à ObjectDataSource où une méthode d'une classe est récupérée par réflexion sans remonter dans la hiérarchie d'héritage. Évidemment, cela ne se passe pas ici.

Ceci est possible, j'ai dû mettre en œuvre un modèle similaire lorsque j'ai conçu une solution-cadre d'entité personnalisée pour travailler avec ObjectDataSource:

public interface IPrimaryKey<T> where T : IPrimaryKey<T> 
{ 
    int Id { get; } 
} 

public static class IPrimaryKeyTExtension 
{ 
    public static IPrimaryKey<T> GetById<T>(this IQueryable<T> source, int id) where T : IPrimaryKey<T> 
    { 
     return source.Where(pk => pk.Id == id).SingleOrDefault(); 
    } 
} 

public class Person : IPrimaryKey<Person> 
{ 
    public int Id { get; set; } 
} 

Snippet d'utilisation:

var people = new List<Person> 
{ 
    new Person { Id = 1 }, 
    new Person { Id = 2 }, 
    new Person { Id = 3 } 
}; 

var personOne = people.AsQueryable().GetById(1); 
Questions connexes