Repository Extension

Photo by Sharon McCutcheon on Unsplash

Last time I wrote about a Strategy extension for my Builder library that makes it easier to separate my algorithm implementations from my Providers. The Strategy / Builder combination is a good fit, but, things could be better still. For instance, another abstraction I use quite often is Repository. It would be nice to have the same sort of extension for Repository, that I already do for Strategy.

This article covers an extension for the CG.Builder NUGET package that makes it quite easy to serve up Repository objects from Providers in a way that integrates them nicely with the rest of the Builder pipeline.

I’m going to presume that everyone already knows what a Repository is. If not, a Repository is supposed to make a data source (envision something like a database) look like a collection. If you want a more textbook explanation then there are many great write ups and examples on Google.

Just like with the Strategy extension, I’ll want the code to be highly reusable and integrate closely with my Builder library, thereby giving me access to Providers and Setups within my Repository classes. Towards that end, let’s start by defining a base Repository interface:

Just like with the IStrategy interface (see the previous article), we’ll start with a minimal Repository interface. I’m sure everyone has a good notion of what they expect in their Repository objects, so, I’ll just let those people derive from IRepository and build that for themselves.

Next step is to make an associated base class, which is shown here:

Once again, just like with the StrategyBase class, we take the opportunity to create a type-safe association between the Product, Provider, Setup, and implicitly, the Repository itself. This gives any derived Repository classes access to anything they’ll need to perform their role.

The next step is to define interfaces for the Repository specific Provider and Setup:

Pretty much exactly what we’d expect, just placeholder types to allow the RepositoryBase class to restrict the types of Provider and Setup that can be used to Repository specific types.

The base class for the Provider looks like this:

The base class for the Setup looks like this:

That’s really all it takes to integration the notion of a Repository into the Builder. Now let’s look at a completely contrived example of how to use this extension:

This example program asks for your first name. It responds by printing your last name – assuming you exist in the database, I suppose. To do that, we create a builder, add a setup to that builder, configure the setup with a configuration string for the Repository, then enter the main loop and start perform first to last name conversions.

So, for the code above to work, we first need to have a MyBuilder class. Let’s see what that looks like:

The MyBuilder class wants to create a Product – in this case an instance of the MyProduct class. Let’s see what the MyProduct class looks like:

The MyProduct class uses it’s collection of Providers to create a Repository for making the conversion from first name to last. This way, the provider stays nice and lean and we can swap out our Repository, should we need to connect to a different database, later on The MyRepository class holds the actual logic for making the conversion. Let’s go look at that class next:

The Repository uses the person’s first name to make the database lookup for the associated last name. The strongly typed association between the Repository and the Setup, thanks to the RepositoryBase base class, means that the Repository has quick access to the entire configuration for the Repository.

Here’s the code for the MyProvider class:

Nice, simple provider. Just the way we like it. All the actual logic is encapsulated in the MyRepository class, where it should be.

Here’s a look at the MySetup class:

This is a pretty typical Setup class with Set… methods for putting values into setup properties, and Get… method for returning those values back again. Keep in mind that a Setup should contain properties for everything a Provider may need at runtime.

Let’s look at the code we used to inject the MySetup into the MyBuilder instance, in the main method of the example:

Like I mention in the last article, there’s actually nothing saying you have to add setups to builders this way, but, this approach does make the process cleaner and allows you to restrict what sorts of Builder classes your Setup class can work with by changing the type of the Builder parameter. For instance, if the method used IBuilder for the parameter type then the MyProvider type could be injected into any Builder type, not just into a MyBuilder type.

So to summarize, creating a Repository type, along with a RepositoryProvider and RepositorySetup type, help us extend the Builder library and easily dispense Repository objects from Providers. Those Repository types are integrated with the Builder and easy to work with. By creating a RepositoryBase class we were able to create a typesafe association between a Repository and it’s Product, Provider and Setup.

 

The code for this article is part of my NUGET package CG.Builder.Repository, which can be downloaded for free at:

https://github.com/CodeGator/CG.Builder.Repository

 

The source code for the CG.Builder.Repository package lives on Github and can be obtained for free at:

https://www.nuget.org/packages/CG.Builder.Repository

That’s about it. I hope this article was helpful. Have fun with the code!