使 LINQ 扩展方法适用于我的班级

Posted

技术标签:

【中文标题】使 LINQ 扩展方法适用于我的班级【英文标题】:Make LINQ extension methods apply to my class 【发布时间】:2013-10-16 21:51:33 【问题描述】:

我有一个 Repository 类,作为方法 FromStore<TEntity> 如下:

IQueryable<TEntity> FromStore<TEntity>() where TEntity : class;

使用它,我可以执行以下操作:

MyRepository.FromStore<DatabaseModel>().SingleOrDefault(dm => dm.Id = Id);

现在,我认为当我可以直接提供 SingleOrDefault 方法时让类的用户调用 FromStore 是愚蠢的(您只需要指定泛型类型参数,而不是像通常那样推断它案例)。

所以,我写了一个方法如下:

public TEntity SingleOrDefault<TEntity>(Expression<Func<TEntity, bool>> filter) where TEntity : class

    return FromStore<TEntity>().SingleOrDefault(filter);

太棒了!现在我可以这样做了:

MyRepository.SingleOrDefault<DatabaseModel>(dm => dm.Id = Id);

但是,我想对所有 linq 扩展方法执行相同的操作。 目前我能想到的唯一方法是在我的类上为每个 linq 方法创建类似的包装器方法。

这看起来很傻,肯定有更好的方法吗?

我在想我能否以某种方式让我的 Repository 类继承 linq 扩展方法扩展的类,但它们扩展了 IQueriable&lt;T&gt;。我的班级没有实现这一点,因为存储库中不仅有一个 T


即使我无法为特定的T 实现IQueryable&lt;T&gt;,我能否以某种方式将 linq 扩展方法应用于我的班级?

【问题讨论】:

更复杂的是,存储库实际上实现了IRepository,这是 API 的用户将看到的。所以我认为扩展方法必须在那里应用(不知何故??)。如果有没有接口的解决方案,但我会感兴趣。 我不认为你可以做到这一点,除非有某种方式使用dynamic。任何解决方案都可能比要求您的客户致电FromStore 更麻烦。 认为可能是这样。如果我能实现IQuerable&lt;&gt;(没有指定T)就好了!不过,我会等着看是否有人有其他想法。 如果您知道您可能需要的所有TEntities,您可以为每个具体类显式实现IQueryable&lt;TEntity&gt;。但是,如果不先明确地转换您的存储库,您仍然无法使用 Linq 扩展方法,这在一定程度上违背了目的。 我非常努力地设想一个具有 generic 方法 Something&lt;T&gt;non-generic 类,而无需声明该方法本身...我不能:( 【参考方案1】:

您可以将其实现为存储库接口的扩展方法。

public static class RepositoryExtensions

    public static TEntity SingleOrDefault<TEntity>(
        this IRepository repository,
        Expression<Func<TEntity, bool>> filter
    )
    
        return repository.FromStore<TEntity>().SingleOrDefault(filter);
    

【讨论】:

感谢您的回答。可能我通过提到接口混淆了事情。我想知道是否可以避免为每个 linq 扩展方法编写类似上面的内容。 我想为了做到这一点,您需要编写自己的 linq 提供程序。这需要implementing a Query Provider。 嗯,好的。不过,我真的可以理解它的外观,同时能够自动使用扩展方法。 IQueryable(T)Queryable 中有自己独立的扩展方法。底层表达式树 (IQueryable.Expression) 使用方法调用 (WhereGroupByOrderBySelect 等) 及其参数构建,您可以使用这些参数来塑造数据。 我了解查询提供程序是如何工作的(在基本层面上),但据我了解,我最终还是会得到一个具有创建查询方法的存储库(现在是一个查询提供程序)。对我来说,这似乎与我现在的 fromstore 方法相同。一定有我遗漏的东西。

以上是关于使 LINQ 扩展方法适用于我的班级的主要内容,如果未能解决你的问题,请参考以下文章

扩展方法和Enumerable

如何获取 Roslyn 中 NamedTypeSymbol 的所有适用方法,包括扩展方法?

LINQ中的扩展方法

创建 Where 查询的 LINQ 扩展方法

Linq 中 Enumerable.Zip 扩展方法有啥用?

动态 linq:创建生成 JSON 结果的扩展方法