PsdExtensions.BootstrapModules 1.0.0

dotnet add package PsdExtensions.BootstrapModules --version 1.0.0
                    
NuGet\Install-Package PsdExtensions.BootstrapModules -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="PsdExtensions.BootstrapModules" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="PsdExtensions.BootstrapModules" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="PsdExtensions.BootstrapModules" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add PsdExtensions.BootstrapModules --version 1.0.0
                    
#r "nuget: PsdExtensions.BootstrapModules, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package PsdExtensions.BootstrapModules@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=PsdExtensions.BootstrapModules&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=PsdExtensions.BootstrapModules&version=1.0.0
                    
Install as a Cake Tool

How do I use it?

First, lets create some models to work with

public sealed class HostModule : HostBootstrapModule
{
    public override Task ConfigureAsync(IHostBuilder builder, BootstrapParameters parameters)
	{
	    builder.ConfigureServices(b =>
	    {
	    	b.AddHostedService<MyBackgroundService>();
	    });

	    return Task.CompletedTask;
	}
}

public sealed class MyBackgroundService : BackgroundService
{
	private readonly ILogger<MyBackgroundService> _logger;

	public MyBackgroundService(ILogger<MyBackgroundService> logger)
	{
		_logger = logger;
	}

	protected override Task ExecuteAsync(CancellationToken stoppingToken)
	{
	    _logger.LogInformation("Hello, World!");
	    return Task.CompletedTask;
	}
}

Now lets run it

// Program.cs
var modules = new BootstrapModules<IHostBuilder>();
var builder = Host.CreateDefaultBuilder();

await modules.ConfigureAsync(builder);

var app = builder.Build();

await app.RunAsync();

Consider these constraints:

  • A Module must be an non-static, non-abstract class.
  • A Module must implement the BootstrapModule<> base class.
  • A Module must contain a public empty constructor.
  • A Module must implement the exact types that will be used later. Assignable base types are not supported for performance reasons.

Example of an unsupported assignable base type approach:

public sealed class MyModule : BootstrapModule<IServiceCollection>
{ ... }

// here is where the issue lies;
// even though ServiceCollection is assignable to IServiceCollection
// native comparer of generic types does not know that
// so in that case Type<IServiceCollection> will NOT equal Type<ServiceCollection>
var modules = new BootstrapModules<ServiceCollection>();

// correct approach
var modules = new BootstrapModules<IServiceCollection>();
This is also the case for .UseAsync<TApp> method, where TApp must be a complete match with the target type of a module.

Custom builders for modules

public sealed class MyCustomModule : BootstrapModule<MyCustomBuilder>
{
    public override Task ConfigureAsync(MyCustomBuilder builder, BootstrapParameters parameters)
	{
	    return Task.CompletedTask;
	}
}

With a produced app support

public sealed class MyCustomModule : BootstrapModule<MyCustomBuilder, MyCustomApp>
{
    public override Task ConfigureAsync(MyCustomBuilder builder, BootstrapParameters parameters)
	{
	    return Task.CompletedTask;
	}

	public override Task UseAsync(MyCustomApp app, BootstrapParameters parameters)
	{
	    return Task.CompletedTask;
	}
}

How to use the produced app in the modules

var modules = new BootstrapModules<IHostBuilder>();
var builder = Host.CreateDefaultBuilder();

await modules.ConfigureAsync(builder);

var app = builder.Build();

await modules.UseAsync(app);

await app.RunAsync();

.ConfigureAsync can be skipped all along if needed

var modules = new BootstrapModules<IHostBuilder>();
var builder = Host.CreateDefaultBuilder();
var app = builder.Build();

await modules.UseAsync(app, ignoreConfiguration: true);

await app.RunAsync();

Group keys

You can seperate certain modules by keys. Key is an object, meaning you can provide a string, enum (recommended), or any other object.

enum ModuleKeys { Primary, Secondary }

[BootstrapModuleOptions(GroupKeys = [ModuleKeys.Primary])]
public sealed class FirstHostModule : HostBootstrapModule
{ ... }

[BootstrapModuleOptions(GroupKeys = [ModuleKeys.Secondary])]
public sealed class SecondHostModule : HostBootstrapModule
{ ... }

[BootstrapModuleOptions(GroupKeys = [ModuleKeys.Primary, ModuleKeys.Secondary])]
public sealed class SharedHostModule : HostBootstrapModule
{ ... }

Now you can filter the modules

var options = new BootstrapModulesOptions()
{
	GroupKey = ModuleKeys.Primary
}

var modules = new BootstrapModules<IHostBuilder>();
var builder = Host.CreateDefaultBuilder();

await modules.ConfigureAsync(builder, options);

var app = builder.Build();
await app.RunAsync();

Orders

You can configure the execution sequence of the modules. By default the execution order for each module is set to 0, meaning the sequence is undefined.

// First
[BootstrapModuleOptions(ExecutionOrder = -1)]
public sealed class SecondHostModule : HostBootstrapModule
{ ... }

// Second
[BootstrapModuleOptions(ExecutionOrder = 0)]
public sealed class FirstHostModule : HostBootstrapModule
{ ... }

// Third
[BootstrapModuleOptions(ExecutionOrder = 1)]
public sealed class SecondHostModule : HostBootstrapModule
{ ... }

Discovery assembly filtering

By default, the discoverer will search for the modules within the assembly that called the .ConfigureAsync()/.UseAsync() methods, OR the assembly that instantiated the BootstrapModulesOptions object. BootstrapModulesOptions stores the assembly reference, but if options are not provided, .ConfigureAsync()/.UseAsync() methods create a default one, which brings the same result. But this doesn't always have to be the case.

var options = new BootstrapModulesOptions()
{
	AssemblyFilter = (a) => a.FullName?.StartsWith(nameof(MyNamespace)) == true
}
This will filter out the unnecessary assemblies from the AppDomain, which will improve the performance of your application.

Parameters

We can provide parameters to the .ConfigureAsync()/.UseAsync() methods for the target modules.

var options = new BootstrapModulesOptions()
{
    ParameterConfiguration = (b) =>
    {
        b.AddParameter("key", "value");
		b.AddParameter(myUniqueObject);
    }
};

Obtaining the parameters

public sealed class MyModule : HostBootstrapModule
{ 
	public override Task ConfigureAsync(IHostBuilder builder, BootstrapParameters parameters)
	{
		object? param = parameters.GetParameter("key");
		// OR
		string? stronglyTypedParam = parameters.GetParameter<string>("key");
		// OR
		string? keylessParam = parameters.GetParameter<string>();

	    return Task.CompletedTask;
	}
}
Important notes
  • Parameter's key, as well as the value, are both of type object.
  • If you were to provide a key-less parameter (as shown in the example on the second line), the value's type must be unique.

Nuget

https://www.nuget.org/packages/PsdExtensions.BootstrapModules

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on PsdExtensions.BootstrapModules:

Package Downloads
PsdExtensions.BootstrapModules.AspNetCore

An extension library for PsdExtensions.BootstrapModules that includes template specifically designed for AspNetCore.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 28 1/25/2026