2008-09-17 121 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);