bbv.Common.Bootstrapper Tutorial Part 4

Strategy

The strategy defines the order of execution for extension points and behaviors. The custom strategy must inherit from IStrategy. For convenience, use the provided abstract base class AbstractStrategy{TExtension} which simplifies defining a custom strategy. The strategy could look like the following:

    public class CustomStrategy : AbstractStrategy<ICustomExtension>
    {
        private readonly Collection<IModule> modules;
        private readonly Lazy<IContainer> container;

        public CustomStrategy()
        {
            this.modules = new Collection<IModule>();
            this.container = new Lazy<IContainer>(() => new Container());
        }

        protected override void DefineRunSyntax(ISyntaxBuilder<ICustomExtension> builder)
        {
            builder
                .Begin
                    .With(new ConfigurationSectionBehavior())
                    .With(new ExtensionConfigurationSectionBehavior())
                .Execute(extension => extension.Start())
                .Execute(() => this.modules, (extension, modules) => extension.ContainerInitializing(modules))
                    .With(modules => new ModuleProvidingBehavior(modules))
                .Execute(() => this.BuildContainer(), (extension, container) => extension.ContainerInitialized(ctx))
                    .With(container => container.Resolve<IBehavior<ICustomExtension>>())
                .Execute(extension => extension.Ready());
        }

        protected override void DefineShutdownSyntax(ISyntaxBuilder<ICustomExtension> builder)
        {
            builder
                .Execute(extension => extension.Stop())
                .End.With(new DisposeExtensionBehavior());
        }

        protected override void Dispose(bool disposing)
        {
            // Dispose the container
            base.Dispose(disposing);
        }

        private IContainer BuildContainer()
        {
            var lazyContainer = this.container.Value;
            foreach (IModule module in this.modules) {
                module.Load(lazyContainer);
            }
            return lazyContainer;
        }
    }

The strategy above would configure the applications startup and shutdown phase to:

  • During startup
  • before calling any extension point load configuration sections
  • and then load extension configuration sections.
  • Call the extension point Start on all registered extensions
  • Initialize the context with this.modules and call the extension point ContainerInitializing with the context on all registered extensions
  • Execute the behavior ModuleProvidingBehavior which gains access to the context.
  • Initialize the context by calling BuildContainer and call the extension point ContainerInitialized with the context on all registered extensions
  • Execute the lazy resolved IBehavior<ICustomExtension>
  • Call the extension point Ready on all registered extensions
  • During shutdown
  • call the extension point Stop on all registered extensions
  • dispose all extensions which implement IDisposable

The strategy above shows part of the fluent definition syntax the bootstrapper uses to gain knowledge about the startup and shutdown phase of the system. Here the Extended Backus-Naur-Form of the syntax:

Syntax = [ Begin ] { Execute } [ End ] .
Begin = "Begin" { With } | End .
End = "End" { EndWith } .
Execute = "Execute" ExecuteAction | ExecuteActionOnExtension | ExecuteActionOnExtensionWithContext .
ExecuteAction = "Expression<Action>" { With | Execute | End } .
ExecuteActionOnExtension = "Expression<Action<TExtension>>" { With | Execute | End } .
ExecuteActionOnExtensionWithContext = "Expression<Func<TContext>>" "Expression<Action<TExtension, TContext>>" { WithOnContext | Execute | EndWithOnContext } .
With = "With" Behavior | LazyBehavior { With | Execute | End } .
WithOnContext = "With" LazyBehaviorWithContext { WithOnContext | Execute | EndWithOnContext } .
EndWith = Behavior | LazyBehavior { EndWith } .
EndWithOnContext = LazyBehaviorWithContext { EndWithOnContext } .
Behavior = "IBehavior<TExtension>" .
LazyBehavior = "Expression<Func<IBehavior<TExtension>>>" .
LazyBehaviorWithContext = "Expression<Func<TContext, IBehavior<TExtension>>>" .

Here the visualized form

The next post will cover more such as configuration sections and reporting. Stay sharp 😉

About the author

Daniel Marbach

Add comment

By Daniel Marbach

Recent Posts