c# – Suggested OO Design Pattern for a Query Builder

Essentially, I’m building a Query Builder (in C#, if that’s relevant) which has this sort of interface, exposing more statically typed functions as the query gets more refined.

AnimalQueryBuilder
 - HasId(id): AnimalQueryBuilder
 - IsHealthy(): AnimalQueryBuilder
 - IsDog(): DogQueryBuilder
 - IsCat(): CatQueryBuilder

DogQueryBuilder
 - NumberOfPuppies(count): DogQueryBuilder
 - TailLengthBetween(start, end): DogQueryBuilder

CatQueryBuilder
 - AverageMeowsPerDayBetween(start, end): CatQueryBuilder
 - LikesMilk(): CatQueryBuilder

Essentially, starting from an AnimalQueryBuilder, I want to be able to do the following actions, to build a query in a fluent way:
var builder = new AnimalQueryBuilder().IsHeathy().IsDog().NumberOfPuppies(4);

This currently works but means that you can’t structure the query like so:
var builder = new AnimalQueryBuilder().IsDog().NumberOfPuppies(4).HasId(21);
Because HasId is not exposed on the DogQueryBuilder

The way that I can get that to currently work is by having DogQueryBuilder and CatQueryBuilder inherit from AnimalQueryBuilder but then you’d be able to do actions which are invalid, like:
var builder = new AnimalQueryBuilder().IsDog().NumberOfPuppies(4).IsCat();

  • Is there a design pattern that already exists for something like this?
  • Should it just go down the first route of not exposing higher up functions (HasId) the more it gets refined and enforce that sort of order?