-
Type:
Improvement
-
Resolution: Done
-
Priority:
Minor - P4
-
None
-
Affects Version/s: 1.1
-
Component/s: None
-
None
-
None
-
Minor Change
-
None
-
None
-
None
-
None
-
None
-
None
QueryConditionList and QueryNotConditionList have a bunch of similar methods – All, ElemMatch, Exists, GT, GTE, In, LT, LTE, Mod, NE, NotIn, Size, Type. An application would like to build queries dynamically chaining them, say, in this way:
BaseQueryConditionList GT(BaseQueryConditionList conditionList, BsonValue value)
{ return conditionList.GT(value); }This scenario is not possible now. The application has to (just for example):
QueryComplete GT(QueryComplete conditionList, BsonValue value)
{ if (conditionList is QueryConditionList) return ((QueryConditionList)conditionList).GT(value); else if (conditionList is QueryNotConditionList) return ((QueryNotConditionList)conditionList).GT(value); else throw new InvalidArgumentException(); }This is equally awkward to write and not effective at runtime. The proposal is to derive these two classes from the same abstract class or introduce a common interface and make these classes to implement it.
Related question about QueryConditionList and QueryNotConditionList. QueryConditionList has Within* methods, QueryNotConditionList does not. Is this difference intentional?
==
Details and potential drawbacks. If we go with, say, the abstract base class then common methods should change their return values to that base class. That is:
QueryConditionList All(BsonArray values) // QueryConditionList
QueryNotConditionList All(BsonArray values) // QueryNotConditionList
Should be:
BaseQueryConditionList All(BsonArray values) // QueryConditionList
BaseQueryConditionList All(BsonArray values) // QueryNotConditionList
Is this going to be troublesome? Of course it is breaking (but it should not be difficult to adopt). As for the other drawbacks, I cannot see them (but I see many advantages). What do you think, who reads this?
==
As far as I can see, many methods in these two classes have duplicated code. A base class could have them implemented in one place (virtual methods perhaps would not even be needed).
Example:
// MongoDB.Driver.Builders.QueryConditionList
public QueryConditionList ElemMatch(IMongoQuery query)
{
this.conditions.Add("$elemMatch", query.ToBsonDocument<IMongoQuery>());
return this;
}
// MongoDB.Driver.Builders.QueryNotConditionList
public QueryNotConditionList ElemMatch(IMongoQuery query)
{
this.conditions.Add("$elemMatch", query.ToBsonDocument<IMongoQuery>());
return this;
}
and etc.
Instead, it could be the only method of BaseQueryConditionList:
// MongoDB.Driver.Builders.BaseQueryConditionList
public BaseQueryConditionList ElemMatch(IMongoQuery query)
{
this.conditions.Add("$elemMatch", query.ToBsonDocument<IMongoQuery>());
return this;
}