First, let’s look at the ‘beginning’ of the fluent interface: the Query() extension method.
123456789101112131415
publicstaticclassQueryExtensions{publicstaticIQueriesQuery(thisSessionsession){returnnewQueries(session);}// If we're using XAF, do the same for ObjectSpace as wellpublicstaticIQueriesQuery(thisIObjectSpaceobjectSpace){varxpObjectSpace=objectSpaceasXPObjectSpace;varsession=xpObjectSpace.Session;returnnewQueries(session);}}
publicinterfaceIQueries{IQueriesInTransaction{get;}IContactQueriesContacts{get;}// One for each queryable object type, e.g.,// IDepartmentQueries Departments { get; } // ITaskQueries Tasks { get; }// etc.}publicclassQueries:IQueries{publicQueries(Sessionsession){_Session=session;}privatereadonlySession_Session;privatebool_InTransaction;publicIQueriesInTransaction{get{_InTransaction=true;returnthis;}}privateIContactQueries_Contacts;publicIContactQueriesContacts{get{if(_Contacts==null)_Contacts=newContactQueries(_Session,_InTransaction);return_Contacts;}}}
If we ignore the InTransaction property, it is just a container for the IContactQueries. In your application, you would have a similar property for each queryable object type. A new ContactQueries instance is created on demand taking into account the whether the InTransaction property was visited earlier in the syntax.
Side note: the inclusion of IFluentInterface is a clever trick to improve Intellisense by hiding the System.Object members such as ToString(). See Daniel Cazzulino’s blog post.
And now we can implement the Contact generic as follows:
Much more readable. Also more maintainable because all queries are in one place and make use of good old LINQ. It’s also easier to test the queries because they are independent of the calling code.