Bootstrappers should be implemented as abstract classes - the idea being that the end users inherit from a specific bootstrapper implementation and override whatever they need to (if anything) to get things configured as they want.
It is recommended that any virtual/abstract methods from NancyBootStrapperBase are sealed in the bootstrapper implementation where it doesn't make sense for the user to override them. This is simply to cut down on clutter and to try and give us the largest opening to the pit of success :-) The DefaultNancyBootStrapper does this.
If you are implementing everything there are several "stages" to initialising the container. Firstly, the stuff that happens at application startup:
The following is called per-request:
Most modern containers support ASP.NET per-request lifetimes, which is great, but as Nancy is intended to run on things other than ASP.NET, that can't be the only solution. To this end we have a separate interface,
INancyBootStrapperPerRequestRegistration<T> (although it might get renamed ;-)). This interface provides a single method called
ConfigureRequestContainer(), which should be implemented as a virtual method in the Bootstrapper, that allows the user to register any dependencies that should only live for the lifetime of that request. Now, when
GetModuleByKey() is called, the workflow should be:
Get a child container from the main container -> pass child container to
ConfigureRequestContainer -> user registers types (usually singletons like UoW) -> Bootstrapper uses the child container to resolve the module(s)