Skip to content

The ISuiteModule

The ISuiteModule is the core of the Suite Framework. Its interface provides hooks for extending the application being composed.

Technically speaking, there are currently two kinds of modules:

  1. .NET Modules for building CLIs, long-lived processes, sidecar containers, migration processes, etc.
  2. ASP.NET Core Module for building ASP.NET Core Applications like Web APIs.

In an ASP.NET Core application, both kinds of modules are present, since in essence an ASP.NET Core application is a console application as well.

In the following sections we'll review the internals of Suite Modules, its features, and which are the different Lifecycle Hooks available.

A Suite Module is any public non-abstract class implementing the ISuiteModule interface.

In order for a Suite Module to be discovered and included in the bootstrapping process, it must be a dependency of the Root Module, either by directly adding the dependency, or by any other module at any level of the dependency tree.

For convenience, there is a SuiteModule class with virtual methods that can be used instead of the ISuiteModule interface for simple cases where a single method needs to be overridden, for example. Bear in mind that there's no difference at all between extending SuiteModule or ISuiteModule; internally the Suite Framework will always require an ISuiteModule.

Dependency Injection

Since Suite modules are resolved using the Bootstrap Services, hence they may use Constructor Dependency Injection to inject certain symbols.

Warning

Remember, the app is not built yet. You may only inject Bootstrap Services. Read more at the Bootstrapping Process

By default, the ConfigureSuiteAppForRootModule and ConfigureSuiteWebAppForRootModule will register the following Bootstrap Services:

  1. The IHostEnvironment
  2. The Application's IConfiguration
    1. Note that, at this stage, this includes vanilla ASP.NET Core stuff like the appsettings.json, however it does not include module calls to ContributeAppConfiguration
  3. The logger through ILogger<T>.

Other services may be added by calling ConfigureBootstrapServices() extension on the IHostBuilder. However, bear in mind that these are instantiated only during bootstrapping and are "forgotten" afterwards.

Warning

In a normal Suite Application, you do not need to use ConfigureBootstrapServices at all. You add services through module's ConfigureServices. These features are for Framework Modules and or workarounds / PoC testing, etc.

C#
public class SampleModule : SuiteModule
{
    private readonly ILogger<SampleModule> logger;

    public SampleModule(
        ILogger<SampleModule> logger,
        IHostEnvironment env)
    {
        this.logger = logger;
        logger.LogInformation("Starting {appName}. Running in {environmentName}",
            env.ApplicationName,
            env.EnvironmentName);
    }
}

Lifecycle Hooks

SetupModule

After a module is instantiated, SetupModule will be called. In this method, your module sets itself up, usually modules will:

  1. Depend on other modules, through builder.DependsOn<OtherModule>.
  2. Depend on and configure other modules, through builder.DependsOn<OtherModule, OtherModuleConfiguration>.
  3. Provide Module Options, through builder.AddOptions<MyModuleOptions>. read more
  4. Extend the Suite Application Configuration, through builder.ContributeAppConfiguration. read more

Note that, since dependencies are declared in SetupModule, this method will not be called in any particular order.

Note

SetupModule should not contain any logic! If you feel the need to have your SetupModule run after your dependencies, ask for help on the Suite Team!

ConfigureServices

After all modules are instantiated and set-up, ConfigureServices will be called. In ConfigureServices, the module is expected to declare all the services that it provides using the provided IServiceCollection. Bear in mind that the recommended way for Modules to provide dependencies is to use the Dependency Injection Engine either by using Attributes or implementing lifetime interfaces.

If the module has declared Module Options at SetupModule, these may be resolved at this stage through the context.GetModuleOptions<TModuleOptions>. Together with this and the IConfiguration, the module is able to configure which services are registered based on configuration.

The execution order is determined by the module's dependencies, meaning that your module's ConfigureServices will run after all the ConfigureServices of the modules you depend on.

Note

ASP.NET Modules include another Lifecycle hook for configuring middlewares. You can read about it here