2008-09-17 84 views
6

受MVC店面的啓發,我正在開發的最新項目是使用IQueryable上的擴展方法來過濾結果。擴展方法不適用於接口

我有這個接口;

IPrimaryKey 
{ 
    int ID { get; } 
} 

,我有這樣的擴展方法

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

比方說,我有一個類,SimpleObj它實現IPrimaryKey。當我有一個SimpleObj的IQueryable時,GetByID方法不存在,除非我明確地將其轉換爲IPrimaryKey的IQueryable,這並不理想。

我在這裏錯過了什麼嗎?

回答

13

它的工作原理,如果做得對。 cfeduke的解決方案起作用。不過,你不必讓IPrimaryKey接口通用,其實,你不必改變你的原始定義:

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

優秀的 - 我接受的原答覆。我明天會試試這個。謝謝你們。 – Kirschstein 2008-09-17 17:25:32

2

由於泛型沒有遵循繼承模式的能力,因此無法工作。即。 IQueryable的<SimpleObj>不是IQueryable的<IPrimaryKey>

4

編輯的繼承樹:Konrad的解決方案是更好,因爲它的簡單得多。下面的解決方案可以工作,但只有在類似於ObjectDataSource的情況下才需要,在這種情況下,通過反射檢索類的方法,而不需要繼承繼承層次結構。顯然這不是發生在這裏。

這是可能的,我已經實現了類似的模式時,我設計了一個自定義實體框架解決方案與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; } 
} 

片段使用:

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

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