Skip to content

Dependency and middleware registrations

When developing Framework Modules, it is quite common that they need custom dependency injection registrations, or calling extension methods on IServiceCollection, or registering one/multiple middlewares.

When the ISuiteModule implementation gets big, either by ConfigureServices or ConfigureMiddleware, we recommend refactoring into internal extension methods over IServiceCollection to clean up the module's definition file, and improve its maintainability.

Extension methods can be defined either for dependency registrations, and/or for middleware registrations. In both cases the goal is the same: maintainability.

As an example, let's take the following module's definition:

C#
namespace ITsynch.Suite.App.Modules
{
    public class MyModule : SuiteModule
    {
        /// <inheritdoc/>
        public override void ConfigureServices(
            IServiceCollection services,
            ModuleConfigurationContext context)
        {
            services.AddTransient<IMyDependency1,MyDependency1>();
            services.AddTransient<IMyDependency2,MyDependency2>();
            services.AddTransient<IMyDependency3,MyDependency3>();
        }
    }
}

After moving registrations to extension method, the module's definition looks like this:

C#
namespace ITsynch.Suite.App.Modules
{
    public class MyModule : SuiteModule
    {
        /// <inheritdoc/>
        public override void ConfigureServices(
            IServiceCollection services,
            ModuleConfigurationContext context)
        {
            services.AddMyModule();
        }
    }
}

Finally, the extension method is defined like this:

C#
namespace ITsynch.Suite.App.Modules
{
    internal static class MyModuleServiceCollectionExtensions
    {
        internal static IServiceCollection AddMyModule(this IServiceCollection services)
        {
            services.AddTransient<IMyDependency1,MyDependency1>();
            services.AddTransient<IMyDependency2,MyDependency2>();
            services.AddTransient<IMyDependency3,MyDependency3>();
            return services;
        }
    }
}

As said before, the same strategy could be taken for middleware registration, in such case the method should be named as Use{ModuleName} instead of the Add suffix.

Convention

  1. Make extension methods internals. These are not to be reused by consumers of the module.
  2. Declare extension methods in the same namespace as the module, which should be ITsynch.Suite.App.Modules.
  3. For ConfigureServices, declare the extension method over IServiceCollection following the naming convention: Add{ModuleName}Module. i.e AddServiceDiscoveryModule.
  4. For ConfigureMiddlewares, declare the extension method over IApplicationBuilder following the naming convention Use{ModuleName}Module. i.e UseServiceDiscoveryModule.
  5. If required, provide the ModuleConfigurationContext or your ModuleOptions instance, ILogger, etc as the extension method's arguments.