简体   繁体   English

扩展方法不适用于接口

[英]Extension Methods not working for an interface

Inspired by the MVC storefront the latest project I'm working on is using extension methods on IQueryable to filter results. 受MVC店面的启发,我正在研究的最新项目是使用IQueryable上的扩展方法来过滤结果。

I have this interface; 我有这个界面;

IPrimaryKey
{
  int ID { get; }
}

and I have this extension method 我有这种扩展方法

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

Let's say I have a class, SimpleObj which implements IPrimaryKey. 假设我有一个实现IPrimaryKey的类SimpleObj。 When I have an IQueryable of SimpleObj the GetByID method doesn't exist, unless I explicitally cast as an IQueryable of IPrimaryKey, which is less than ideal. 当我有一个SimpleObj的IQueryable时,GetByID方法不存在,除非我明确地转换为IPrimaryKey的IQueryable,这不太理想。

Am I missing something here? 我在这里错过了什么吗?

It works, when done right. 如果做得好,它可以工作。 cfeduke's solution works. cfeduke的解决方案有效。 However, you don't have to make the IPrimaryKey interface generic, in fact, you don't have to change your original definition at all: 但是,您不必使IPrimaryKey接口通用,事实上,您根本不必更改原始定义:

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

Edit: Konrad 's solution is better because its far simpler. 编辑: 康拉德的解决方案更好,因为它更简单。 The below solution works but is only required in situations similar to ObjectDataSource where a method of a class is retrieved through reflection without walking up the inheritance hierarchy. 下面的解决方案有效但仅在类似于ObjectDataSource的情况下才需要,其中通过反射检索类的方法而不会继承继承层次结构。 Obviously that's not happening here. 显然这不会发生在这里。

This is possible, I've had to implement a similar pattern when I designed a custom entity framework solution for working with 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; }
}

Snippet of use: 使用片段:

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

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

This cannot work due to the fact that generics don't have the ability to follow inheritance patterns. 由于泛型不具备遵循继承模式的能力,因此无法工作。 ie. 即。 IQueryable<SimpleObj> is not in the inheritance tree of IQueryable<IPrimaryKey> IQueryable <SimpleObj>不在IQueryable <IPrimaryKey>的继承树中

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM