Yesterday I detailed my experiences creating my first fluent interface. The implementation of the first attempt at a Where fluent interface can be downloaded here.
However, I wasn't satisfied with leaving the user the ability to do something such as Where().And() or Where().Column("foo").IsEqualTo(0).Column("bar"). Though both of these usages would throw an exception, I prefer a compile time check instead. The solution I was looking for would only allow access to the methods in the correct order. Finding this solution would also remove the need for maintaing the next expected method call.
To achieve this the Where class needed to lose the majority of it's behavoir. The Where class now has only a Column method that returns a new WhereColumn. Additionally, Where no longer implements IWhere. The WhereColumn class still only has an IsEqualTo method; however, this method now returns a CompleteWhere instance.
By adding the CompleteWhere class I was able to limit usage to only correct methods. CompleteWhere implements (the now slimmer) IWhere interface. The only property of the IWhere interface is And. The And property returns a Where instance, which allows you to begin a new column/value condition. CompleteWhere has a few other public methods that are used internally in the .norm framework to build SQL statements. However, correct usage should never return you an instance of CompleteWhere.*
Overall, I am happy with the evolution of the where fluent interface. Version 2 is as easy to use (and less easy to make a mistake with), and the code behind it is simpler. You can download v2 here.
*In the past I would have made the constructor of Where that takes a CompleteWhere instance internal. Additionally, the CompleteWhere class should be internal to ensure that it isn't misused. However, I chose not to take this approach because Zak Tamsen convinced me that I should always provide the rope.