接口无法工作的扩展方法

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时,如果不显式将其转换为IPrimaryKey的IQueryable,则无法使用GetByID方法,这不太理想。
这里我是否漏掉了什么?
3个回答

13

如果正确使用,它就有效。cfeduke的解决方案可行。然而,你不必使IPrimaryKey接口成为通用接口,事实上,你根本不需要改变原始定义:

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

太好了 - 我取消了原来的答案。我明天会尝试这个。谢谢你们两个。 - Kirschstein
1
我只想说我的回答并没有错,它是他的代码无法运行的原因,只是我没有花时间去找出一个解决方案。我已经点赞了你更好的答案。 - Garry Shutler
1
公共静态 T GetByID<T>(this IQueryable<T> source, int id) where T : IPrimaryKey // 更好的集成 - Phil C

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);

2

由于泛型没有遵循继承模式的能力,因此这是不可行的。即 IQueryable<SimpleObj> 不在 IQueryable<IPrimaryKey> 的继承树中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接