【问题标题】:Ambiguous IQueryable<T>.Where and IEnumerable<T>.Where on extension method扩展方法上的模棱两可的 IQueryable<T>.Where 和 IEnumerable<T>.Where
【发布时间】:2016-02-14 03:56:48
【问题描述】:

我正在尝试使用以下扩展方法覆盖我的实体的所有 Where() 方法:

public static IQueryable<T> Where<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate)
{
    throw new SecurityException("Use the security SafeWhere method");
}

但是当我使用 context.EntitiesX.Where() 时出现错误:Queryable(IQueryable, Expression>) 和 Enumerable(IEnumerable, Expression>)

我该如何解决这个问题?此外,我希望该扩展方法仅影响实现某些接口的实体,我已经尝试通过指定接口类型而不是通用 T 来尝试,但这不起作用。

【问题讨论】:

  • 一种解决方法是不要将其编写为扩展方法。把它写成这样的静态方法YourClass.Where(context.EntitiesX , ....)
  • 我想确定基地在哪里被使用
  • 您不能覆盖扩展方法。对于编译器来说,它们与静态方法完全相同,当您有两个具有相同签名的方法时,这将导致歧义。
  • 重定向Where扩展方法的目的是什么?如果它仅适用于您的实体,为什么不给它一个不同的名称并完全消除混淆?
  • “我想确定没有其他地方使用了基础 Where ” 您无法阻止 - 您无法阻止某人使用 Queryable 扩展方法。

标签: c# linq generics entity-framework-6 extension-methods


【解决方案1】:

诀窍是让您的扩展方法比第 3 方(系统)方法具有更高的优先级。

假设你的代码结构是这样的

MyExtensions.cs

using System;
// ... other 3rd party usings

namespace MyExtensionsNamespace
{
    public static class MyExtensions
    {
        public static IQueryable<T> Where<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate)
        {
            throw new SecurityException("Use the security SafeWhere method");
        }
        // ...
    }
}

MyEntity.cs

using System;
using System.Linq;
// ... other 3rd party usings
using MyExtensionsNamespace;

namespace MyEntitiesNamespace
{
    // ...
}

您只需要像这样在命名空间声明之后移动命名空间 usings

MyEntity.cs

using System;
using System.Linq;
// ... other 3rd party usings

namespace MyEntitiesNamespace
{
    using MyExtensionsNamespace;
    // ...
}

附:编译器错误消息具有误导性。它是在使用扩展方法语法时生成的。对于 LINQ 语法,错误是不同的

错误 CS1940 为源类型“DbSet”找到查询模式的多个实现。对“Where”的模棱两可的调用。

【讨论】:

  • 可枚举类没有Where 方法和这个参数Expression&lt;Func&lt;TSource,bool&gt;&gt;,所以似乎不是命名空间的问题
  • @Grundy 我已经复制了它,命名空间确实在解决它。
【解决方案2】:

我还希望该扩展方法只影响实现特定接口的实体,

尝试对您的扩展方法施加通用约束:

public static IQueryable<T> Where<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate)
    where T : IMyInterface
{
    throw new SecurityException("Use the security SafeWhere method");
}

虽然我仍然认为您应该选择不同的名称以避免其他人阅读您的代码时造成任何混淆。

【讨论】:

  • 放置泛型约束并不能解决问题,因为在解决最佳重载时没有考虑泛型约束。我认为 Eric Lippert 有一篇关于此的帖子。唯一的办法是让你的班级“更接近”。
  • @IvanStoev 这不是我要解决的问题的一部分,也是我建议更改名称的原因。通用约束解决仅对实现特定接口的成员可用的要求。
  • 我很抱歉,我以为你正在解决整个问题(现在我看到你肯定没有)。
猜你喜欢
  • 2011-07-28
  • 1970-01-01
  • 2011-11-06
  • 1970-01-01
  • 2011-11-04
  • 2019-10-23
  • 2012-06-23
  • 2010-10-30
相关资源
最近更新 更多