Module Definition
Silky is a modular framework composed of multiple NuGet packages. Each module encapsulates a cohesive set of features with its own logic and scope, independent of other modules.
The Module Class
A module is defined by creating a class in the assembly that derives from SilkyModule:
public class RpcModule : SilkyModule
{
}
SilkyModule is an abstract class that also extends Autofac's Module:
public abstract class SilkyModule : Autofac.Module, ISilkyModule, IDisposable
{
protected SilkyModule()
{
Name = GetType().Name.RemovePostFix(StringComparison.OrdinalIgnoreCase, "Module");
}
// Autofac-level service registration
protected override void Load([NotNull] ContainerBuilder builder)
{
base.Load(builder);
RegisterServices(builder);
}
// Microsoft DI-level service registration
public virtual void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
}
// Additional Autofac registrations (override in derived modules)
protected virtual void RegisterServices([NotNull] ContainerBuilder builder)
{
}
// Called when the application starts
public virtual Task Initialize([NotNull] ApplicationContext applicationContext)
{
return Task.CompletedTask;
}
// Called when the application stops
public virtual Task Shutdown([NotNull] ApplicationContext applicationContext)
{
return Task.CompletedTask;
}
public virtual string Name { get; }
}
The Four Module Roles
| Method | Phase | Purpose |
|---|---|---|
ConfigureServices() | Startup | Register services into IServiceCollection (Microsoft DI) |
RegisterServices() | Startup | Register services into Autofac ContainerBuilder |
Initialize() | Application start | Lifecycle init: open connections, start DotNetty listeners, register service routes |
Shutdown() | Application stop | Cleanup: close connections, deregister routes, release resources |
Module Discovery & Dependency Resolution
Modules declare their dependencies using the [DependsOn] attribute:
[DependsOn(typeof(SilkyRpcModule), typeof(SilkyCachingModule))]
public class OrderModule : SilkyModule
{
}
At startup, ModuleLoader:
- Starts from the user-specified startup module (e.g.,
AppModule) - Recursively reads
[DependsOn]attributes to discover all transitive dependencies - Performs topological sort to produce a deterministic load order (dependencies load before dependents)
- Calls
RegisterServices(builder)for each module in order to configure the Autofac container
Module Lifecycle (InitSilkyHostedService)
After the DI container is built, InitSilkyHostedService (an IHostedService) manages the runtime lifecycle:
public class InitSilkyHostedService : IHostedService
{
private readonly IModuleManager _moduleManager;
public async Task StartAsync(CancellationToken cancellationToken)
{
// Call Initialize() on each module in topological order
await _moduleManager.InitializeModules(applicationContext);
}
public async Task StopAsync(CancellationToken cancellationToken)
{
// Call Shutdown() on each module in reverse topological order
await _moduleManager.ShutdownModules(applicationContext);
}
}
HTTP Modules
For Web Host scenarios, modules that extend SilkyHttpModule also participate in ASP.NET Core middleware pipeline configuration:
public abstract class SilkyHttpModule : SilkyModule
{
// Called during app.UseXxx() middleware setup
public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
}
}
Configure() is called in topological order during the middleware pipeline build phase — after all services are registered and the container is built.
