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.