将类型推断与流畅的接口结合使用

发布于 2025-01-07 06:21:49 字数 1941 浏览 0 评论 0原文

我有一个类/接口层次结构。在接口方面我有

IQuery
  ISelect      (inherits IQuery)
  IUpdate      (inherits IQuery)
  etc

在类方面我有

QueryBase       (implements IQuery)
  SelectQuery   (implements ISelect)
  UpdateQuery   (implements IUpdate)
  etc

显然,例如,Update 和 Select 类共享一个 WHERE 子句,但只有 Select 具有 GROUP BY 功能,因此理想情况下,如果正在创建 Update 查询,流畅的接口将不会给出访问 GROUP BY 功能,但如果创建 SelectQuery 则可以。

例如,在流畅的接口术语中,

  var/Dim select = New SelectQuery()        <- returns ISelect explicit
                          .AddColumn(....)  <- returns ISelect explicit
                          .AddWhere(....)   <- returns ISelect inferred
                          .AddGroupBy(....) <- returns ISelect explicit

  var/Dim update = New UpdateQuery()        <- returns IUpdate explicit
                          .AddSet(....)     <- returns IUpdate explicit
                          .AddWhere(....)   <- returns IUpdate inferred

我不确定如何实现 AddWhere 函数。

以前,我在 IQuery 接口中声明了 AddWhere 函数,

Function AddWhere(ByVal condition As ICriterion) As IQuery

IQuery AddWhere(ICriterion condition)

但因为它返回一个 IQuery,所以我失去了类型推断的好处,因此一旦流畅的接口转换为 IQuery,如果它是一个 Select 查询,创建后,我将无法再访问例如 AddGroupBy 方法。

因此,我尝试将其实现为带有泛型的扩展方法

<Extension>
Public Function AddWhere(Of T As IQuery)(Byval this as T, Byval condition as Condition) as T
    this.SetWhere(condition)
    Return Me
End Function

public T AddWhere<T>(T @this, Condition condition) where T : IQuery
{
    @this.SetWhere(condition);
    return this;
}

,并带有 QueryBase 上的 Friend(内部)方法 SetWhere,以允许我更新 WHERE 子句。但是,由于泛型仅限于 IQuery,因此它无法找到 SetWhere。但是,如果我约束为 QueryBase,那么显然编译器会抛出错误,指出 ISelect 找不到 AddWhere 方法。

我认为我还没有完全正确地实现我想要实现的目标的继承链或接口实现。

(我希望这一点很清楚!!)

如果有人能建议我在扩展方法实现方面出错的地方,或者我应该如何更好地构建我的类/接口层次结构,我将不胜感激。

I have a class /interface hierarchy. On the interface side I have

IQuery
  ISelect      (inherits IQuery)
  IUpdate      (inherits IQuery)
  etc

On the class side I have

QueryBase       (implements IQuery)
  SelectQuery   (implements ISelect)
  UpdateQuery   (implements IUpdate)
  etc

Obviously, for example, both Update and Select classes share a WHERE clause but only a Select has GROUP BY functionality so ideally if an Update Query is being creating, the fluent interface will not give access to GROUP BY functionality but would do if a SelectQuery was being created.

eg in fluent interface terms

  var/Dim select = New SelectQuery()        <- returns ISelect explicit
                          .AddColumn(....)  <- returns ISelect explicit
                          .AddWhere(....)   <- returns ISelect inferred
                          .AddGroupBy(....) <- returns ISelect explicit

  var/Dim update = New UpdateQuery()        <- returns IUpdate explicit
                          .AddSet(....)     <- returns IUpdate explicit
                          .AddWhere(....)   <- returns IUpdate inferred

I am unsure how to implement the AddWhere function.

Previously I had declared the AddWhere function in the IQuery interface as

Function AddWhere(ByVal condition As ICriterion) As IQuery

IQuery AddWhere(ICriterion condition)

but because it was returning an IQuery, I was losing the benefits of the type inference and so as soon as the fluent interface had cast to the IQuery, if it was a Select query being created, I would no longer have access to, eg, the AddGroupBy method.

So I have tried to implement it as an Extension Method with generics

<Extension>
Public Function AddWhere(Of T As IQuery)(Byval this as T, Byval condition as Condition) as T
    this.SetWhere(condition)
    Return Me
End Function

public T AddWhere<T>(T @this, Condition condition) where T : IQuery
{
    @this.SetWhere(condition);
    return this;
}

with a Friend (internal) method, SetWhere, on QueryBase to permit me to update the WHERE clause. However because the generic is constrained to IQuery, it won't find the SetWhere. However, if I constrain as QueryBase, then, obviously, the compiler throws wobblies saying that the ISelect can't find an AddWhere method.

I'm thinking that I haven't quite got the inheritence chain or interface implementations quite right for what I'm trying to achieve.

(I hope that is clear!!)

I'd be grateful if someone could suggest either where I am going wrong in terms of the extension method implementation, or how I should better structure my class/interface hierarchy.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

握住你手 2025-01-14 06:21:49
Public Interface IQuery
    Function AddWhere() As IQuery
End Interface

Public Interface IUpdate : Inherits IQuery
    Overloads Function AddWhere() As IUpdate
End Interface

Public Interface ISelect : Inherits IQuery
    Overloads Function AddWhere() As ISelect
    Function AddGroupBy() As ISelect
End Interface

Public Class QueryBase : Implements IQuery
    Public Function AddWhere() As IQuery Implements IQuery.AddWhere
        ''...
        Return Me
    End Function
End Class

Public Class UpdateQuery : Inherits QueryBase : Implements IUpdate
    Public Shadows Function AddWhere() As IUpdate Implements IUpdate.AddWhere
        MyBase.AddWhere()
        Return Me
    End Function
End Class

Public Class SelectQuery : Inherits QueryBase : Implements ISelect
    Public Shadows Function AddWhere() As ISelect Implements ISelect.AddWhere
        MyBase.AddWhere()
        Return Me
    End Function
    Public Function AddGroupBy() As ISelect Implements ISelect.AddGroupBy
        ''...
        Return Me
    End Function
End Class
Public Interface IQuery
    Function AddWhere() As IQuery
End Interface

Public Interface IUpdate : Inherits IQuery
    Overloads Function AddWhere() As IUpdate
End Interface

Public Interface ISelect : Inherits IQuery
    Overloads Function AddWhere() As ISelect
    Function AddGroupBy() As ISelect
End Interface

Public Class QueryBase : Implements IQuery
    Public Function AddWhere() As IQuery Implements IQuery.AddWhere
        ''...
        Return Me
    End Function
End Class

Public Class UpdateQuery : Inherits QueryBase : Implements IUpdate
    Public Shadows Function AddWhere() As IUpdate Implements IUpdate.AddWhere
        MyBase.AddWhere()
        Return Me
    End Function
End Class

Public Class SelectQuery : Inherits QueryBase : Implements ISelect
    Public Shadows Function AddWhere() As ISelect Implements ISelect.AddWhere
        MyBase.AddWhere()
        Return Me
    End Function
    Public Function AddGroupBy() As ISelect Implements ISelect.AddGroupBy
        ''...
        Return Me
    End Function
End Class
孤独陪着我 2025-01-14 06:21:49

也许您可以在层次结构中使用另一个接口,例如:

interface IQuery

interface IConditional : IQuery

interface ISelect : IConditional

interface IUpdate : IConditional

IConditional 接口可以具有 AddWhere 方法,可以直接在接口定义中,也可以作为约束的扩展方法IConditional 类型。

Perhaps you could use another interface in your hierarchy, something like:

interface IQuery

interface IConditional : IQuery

interface ISelect : IConditional

interface IUpdate : IConditional

The IConditional interface could then have the AddWhere method, either directly in the interface definition or as an extension method constrained on the IConditional type.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文