bbv.Common.Bootstrapper Tutorial Part 2

Advanced

The bootstrapper can do more! Let us look into a more complex scenario. Often it is required to collect context information during the bootstrapping process and pass this information to the extension points.

Imagine you are using an inversion of control container which intakes IModule implementations to register dependencies during the bootstrapping process. All IModule implementations need to be passed into the IContainer implementation upon construction. For backward compatibility the bootstrapper must automatically check whether an extension implements IModuleProvider and register the provided modules on the IContainer implementation.

The application we are designing allocates both managed and unmanaged resources which need to be removed when the application is shutting down. To get this behavior some extension occasionally implement IDisposable which needs to be called when shutting down.

Furthermore the application uses configuration sections to be able to overwrite some default configurations without recompiling the application. These configuration entries must be parsed and passed to the extensions which rely on their existence.

Extension interface

A custom extension interface for this example could look like the following:

    public interface ICustomExtension : IExtension
    {
        void Start();
        void ContainerInitializing(ICollection<IModule> modules);
        void ContainerInitialized(IContainer container);
        void Ready();
        void Stop();
    }

The extension interface above would indicate that the applications extension points are:

  • Start
  • ContainerInitializing which allows to add IModule implementations
  • ContainerInitialized which allows to resolve dependencies on the IContainer
  • Ready
  • Stop

An abstract base class for this use case:

    public abstract class CustomExtensionBase : ICustomExtension
    {
        public string Name
        {
            get { return this.GetType().FullNameToString(); }
        }

        protected IContainer Container { get; private set; }

        public virtual void Start() { }
        public virtual void ContainerInitializing(ICollection<IModule> modules) { }

        public void ContainerInitialized(IContainer container)
        {
            this.Container = container;
            this.ContainerInitializedCore(container);
        }

        public virtual void Ready() { }
        public virtual void Stop() { }
        public abstract string Describe();
        protected virtual void ContainerInitializedCore(IContainer container) { }
    }

This allows inheritors to override only the extension points that they are interested in. The extension interface does not include:

  • the fact that the extensions must be checked whether they implement IModuleProvider
  • the fact that the extensions must be checked whether they implement IDisposable
  • the fact that configuration sections must be loaded for an extension if available

How can we extend the bootstrapping mechanism without modifying the custom extension interface? We need behaviors, but this will be covered in the next post!

About the author

Daniel Marbach

1 comment

By Daniel Marbach

Recent Posts