Using Type Inference with Silent Interfaces

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

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

On the side of class I

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

Obviously, for example, the Update and Select classes share the WHERE clause, but only the Select function has a GROUP BY function, so ideally, if an update request is created, a free interface will not give access to GROUP BY functionality, but will do it if SelectQuery was created.

for example in fluent terms of an interface

  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 not sure how to implement the AddWhere function.

I previously declared the AddWhere function in the IQuery interface as

 Function AddWhere(ByVal condition As ICriterion) As IQuery IQuery AddWhere(ICriterion condition) 

but since it returned IQuery, I lost the benefits of type inference, and as soon as the free interface was passed to IQuery, if it was a Select query, I would no longer have access to, for example, the AddGroupBy method.

So, I 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; } 

using the Friend (internal) SetWhere method on QueryBase to allow me to update the WHERE clause. However, since the general parameter is limited by IQuery, it will not find SetWhere. However, if I restrict myself to QueryBase, then, obviously, the compiler throws wobblies, saying that ISelect cannot find the AddWhere method.

I think that I did not quite understand the chain of inheritance or implementation of the interface is absolutely correct for what I am trying to achieve.

(I hope this is clear!)

I would appreciate it if someone could suggest where I am mistaken in terms of implementing the extension method, or how I should better structure my class / interface hierarchy.

+4
source share
2 answers
 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 
+1
source

Perhaps you could use a different interface in your hierarchy, for example:

 interface IQuery interface IConditional : IQuery interface ISelect : IConditional interface IUpdate : IConditional 

The IConditional interface can then have the AddWhere method either directly in the interface definition, or as an extension method limited to the IConditional type.

0
source

Source: https://habr.com/ru/post/1397002/


All Articles