Baubit.DI.Autofac
2025.51.1
dotnet add package Baubit.DI.Autofac --version 2025.51.1
NuGet\Install-Package Baubit.DI.Autofac -Version 2025.51.1
<PackageReference Include="Baubit.DI.Autofac" Version="2025.51.1" />
<PackageVersion Include="Baubit.DI.Autofac" Version="2025.51.1" />
<PackageReference Include="Baubit.DI.Autofac" />
paket add Baubit.DI.Autofac --version 2025.51.1
#r "nuget: Baubit.DI.Autofac, 2025.51.1"
#:package Baubit.DI.Autofac@2025.51.1
#addin nuget:?package=Baubit.DI.Autofac&version=2025.51.1
#tool nuget:?package=Baubit.DI.Autofac&version=2025.51.1
Baubit.DI.Autofac
Autofac support for Baubit.DI modular dependency injection framework.
Table of Contents
- Installation
- Overview
- Security
- Quick Start
- Application Creation Patterns
- Module Configuration in appsettings.json
- Consumer Module Registration
- API Reference
- License
Installation
dotnet add package Baubit.DI.Autofac
Overview
Baubit.DI.Autofac extends Baubit.DI's modular dependency injection framework with Autofac container support. It enables:
- Module-based service registration using Autofac's
ContainerBuilder - Configuration-driven module composition
- Hybrid loading from both configuration files and code
- Mixed module support: Use both Autofac modules and standard DI modules in the same application
- Full access to Autofac's advanced features (interceptors, decorators, lifetime scopes)
Security
Baubit.DI.Autofac uses compile-time module discovery to eliminate remote code execution (RCE) vulnerabilities from configuration-driven module loading. Modules must be annotated with [BaubitModule] and discovered at compile time. Configuration can only select from these pre-registered modules using simple string keys instead of assembly-qualified type names.
Key security features:
- No reflection-based type loading from configuration
- Compile-time validation of module definitions
- Configuration uses simple string keys, not type names
- Consumer assemblies can register their own modules using
[GeneratedModuleRegistry] - Service provider factory must be explicitly specified (no dynamic type loading from configuration)
Quick Start
1. Define a Configuration
public class MyModuleConfiguration : Baubit.DI.Autofac.Configuration
{
public string ConnectionString { get; set; }
public int PoolSize { get; set; } = 10;
}
2. Create an Autofac Module
[BaubitModule("mymodule")] // Required for configuration-based loading
public class MyModule : Baubit.DI.Autofac.Module<MyModuleConfiguration>
{
// Constructor for loading from IConfiguration (appsettings.json)
public MyModule(IConfiguration configuration)
: base(configuration) { }
// Constructor for programmatic creation
public MyModule(MyModuleConfiguration configuration, List<Baubit.DI.IModule> nestedModules = null)
: base(configuration, nestedModules) { }
public override void Load(ContainerBuilder containerBuilder)
{
// Register using Autofac's ContainerBuilder API
containerBuilder.RegisterType<MyService>()
.As<IMyService>()
.WithParameter("connectionString", Configuration.ConnectionString)
.SingleInstance();
}
}
Note: The [BaubitModule("key")] attribute registers your module for compile-time validated, secure configuration loading. The key is used in appsettings.json instead of assembly-qualified type names.
Application Creation Patterns
Baubit.DI.Autofac supports four patterns for creating applications.
Important: You must call the
Register()method on each module registry (typically 1 per library) before module loading. See Consumer Module Registration.
Pattern 1: Modules from appsettings.json
Load ALL modules from configuration. Module types, their configurations, and nested modules are defined in JSON.
// Register consumer modules first
MyModuleRegistry.Register();
// appsettings.json defines all modules
// Must explicitly specify Autofac factory for security
await Host.CreateApplicationBuilder()
.UseConfiguredServiceProviderFactory<HostApplicationBuilder, Baubit.DI.Autofac.ServiceProviderFactory>()
.Build()
.RunAsync();
appsettings.json:
{
"modules": [
{
"key": "mymodule",
"configuration": {
"connectionString": "Server=localhost;Database=mydb",
"poolSize": 20
}
}
]
}
Use when:
- Module configuration should be externally configurable
- You want to change behavior without recompiling
- All module settings can be expressed in configuration
Pattern 2: Modules from Code (IComponent)
Load ALL modules programmatically using IComponent. No configuration file needed.
// Register consumer modules first
MyModuleRegistry.Register();
// Define a component that builds modules in code
public class MyComponent : Component
{
protected override Result<ComponentBuilder> Build(ComponentBuilder builder)
{
return builder.WithModule<MyModule, MyModuleConfiguration>(
cfg =>
{
cfg.ConnectionString = "Server=localhost;Database=mydb";
cfg.PoolSize = 20;
},
cfg => new MyModule(cfg)
);
}
}
// Load modules from component only (no appsettings.json)
await Host.CreateEmptyApplicationBuilder(new HostApplicationBuilderSettings())
.UseConfiguredServiceProviderFactory<HostApplicationBuilder, Baubit.DI.Autofac.ServiceProviderFactory>(
componentsFactory: () => [new MyComponent()]
)
.Build()
.RunAsync();
Use when:
- Module configuration is determined at compile time
- You need full control over module instantiation
- Configuration values come from code, not files
Pattern 3: Hybrid Loading (appsettings.json + IComponent)
Combine BOTH configuration-based and code-based module loading. This is the most flexible approach.
// Register consumer modules first
MyModuleRegistry.Register();
// Load modules from BOTH appsettings.json AND code
await Host.CreateApplicationBuilder()
.UseConfiguredServiceProviderFactory<HostApplicationBuilder, Baubit.DI.Autofac.ServiceProviderFactory>(
componentsFactory: () => [new MyComponent()]
)
.Build()
.RunAsync();
Loading order:
- Components from
componentsFactoryare loaded first - Modules from appsettings.json
modulessection are loaded second
Use when:
- Some modules need external configuration (database connections, API keys)
- Some modules need compile-time configuration or code-based logic
- You want to extend configuration-based modules with additional code-based ones
Pattern 4: Mixed Autofac and Standard DI Modules
You can use BOTH Autofac modules and standard DI modules in the same application as long as you use Baubit.DI.Autofac.ServiceProviderFactory.
// Register consumer modules first
MyModuleRegistry.Register();
// Autofac module using ContainerBuilder
public class AutofacModule : Baubit.DI.Autofac.Module<MyConfig>
{
public override void Load(ContainerBuilder containerBuilder)
{
containerBuilder.RegisterType<MyService>().As<IMyService>().SingleInstance();
}
}
// Standard DI module using IServiceCollection
public class StandardModule : Baubit.DI.Module<StandardConfig>
{
public override void Load(IServiceCollection services)
{
services.AddSingleton<IOtherService, OtherService>();
}
}
await Host.CreateEmptyApplicationBuilder(new HostApplicationBuilderSettings())
.UseConfiguredServiceProviderFactory<HostApplicationBuilder, Baubit.DI.Autofac.ServiceProviderFactory>(
componentsFactory: () => [
new AutofacComponent(), // Uses Autofac
new StandardComponent() // Uses standard DI
]
)
.Build()
.RunAsync();
How it works:
ServiceProviderFactory.Loadchecks module types at runtime- Autofac modules (implementing
Baubit.DI.Autofac.IModule) register directly withContainerBuilder - Standard DI modules (implementing only
Baubit.DI.IModule) register withIServiceCollection, then populate into Autofac
Use when:
- Gradually migrating from standard DI to Autofac
- Some modules need Autofac features (interceptors, decorators)
- Other modules work fine with standard DI
The full set of sample code can be found here
Module Configuration in appsettings.json
Module configurations can be defined in three ways:
Direct Configuration
Configuration values are enclosed in a configuration section:
{
"modules": [
{
"key": "mymodule",
"configuration": {
"connectionString": "Server=localhost;Database=mydb",
"poolSize": 20,
"modules": [
{
"key": "nested-module",
"configuration": { }
}
]
}
}
]
}
Indirect Configuration
Configuration is loaded from external sources via configurationSource:
{
"modules": [
{
"key": "mymodule",
"configurationSource": {
"jsonUriStrings": ["file://path/to/config.json"]
}
}
]
}
config.json:
{
"connectionString": "Server=localhost;Database=mydb",
"poolSize": 20,
"modules": [
{
"key": "nested-module",
"configuration": {
"somePropKey": "some_prop_value"
}
}
]
}
Hybrid Configuration
Combine direct values with external sources:
{
"modules": [
{
"key": "mymodule",
"configuration": {
"connectionString": "Server=localhost;Database=mydb"
},
"configurationSource": {
"jsonUriStrings": ["file://path/to/additional.json"]
}
}
]
}
additional.json:
{
"poolSize": 20,
"modules": [
{
"key": "nested-module",
"configuration": { }
}
]
}
Consumer Module Registration
Consumer projects (test projects, libraries, plugins) can register their own modules using the [GeneratedModuleRegistry] attribute.
Important: Registry registration must be called before any module loading operations.
Step 1: Install Baubit.DI.Autofac
dotnet add package Baubit.DI.Autofac
The generator is automatically included via the Baubit.DI dependency.
Step 2: Create a Registry Class
using Baubit.DI;
namespace MyProject
{
[GeneratedModuleRegistry]
internal static partial class MyModuleRegistry
{
// Register() method will be generated automatically
}
}
The generator discovers all modules in your assembly marked with [BaubitModule] and generates a Register() method in your namespace.
Step 3: Define Your Modules
[BaubitModule("my-custom-module")]
public class MyCustomModule : Baubit.DI.Autofac.Module<MyConfig>
{
public MyCustomModule(IConfiguration config) : base(config) { }
public override void Load(ContainerBuilder containerBuilder)
{
containerBuilder.RegisterType<MyService>().As<IMyService>().SingleInstance();
}
}
Step 4: Register at Startup
Critical: Call Register() before any module loading:
// MUST be called before any module loading
MyModuleRegistry.Register();
// Now your modules are available in configuration
await Host.CreateApplicationBuilder()
.UseConfiguredServiceProviderFactory<HostApplicationBuilder, Baubit.DI.Autofac.ServiceProviderFactory>()
.Build()
.RunAsync();
Why this is required:
- The main
Baubit.DI.ModuleRegistryonly knows about modules in the Baubit.DI assembly - Consumer assemblies must explicitly register their modules with
ModuleRegistry.RegisterExternal() - The generated
Register()method does this automatically - Registration must happen before
UseConfiguredServiceProviderFactory()initializes the registry
Configuration:
{
"modules": [
{
"key": "my-custom-module",
"configuration": { }
}
]
}
API Reference
<details> <summary><strong>BaubitModuleAttribute</strong></summary>
Marks a module class for compile-time discovery and registration.
| Property | Description |
|---|---|
Key |
Unique string key used in configuration to identify this module |
Usage:
[BaubitModule("mymodule")]
public class MyModule : Baubit.DI.Autofac.Module<MyConfig> { }
Requirements:
- Key must be unique across all modules in the compilation
- Module must implement
IModule - Module must have a constructor accepting
IConfiguration
</details>
<details> <summary><strong>GeneratedModuleRegistryAttribute</strong></summary>
Marks a partial class to receive generated module registry methods for consumer assemblies.
Usage:
[GeneratedModuleRegistry]
internal static partial class MyModuleRegistry
{
// Register() method generated automatically
}
// At application startup:
MyModuleRegistry.Register();
Purpose:
- Allows test projects to register test-specific modules
- Enables consumer libraries to provide their own modules
- Supports plugin architectures with distributed modules
</details>
<details> <summary><strong>IModule</strong></summary>
Interface for Autofac dependency injection modules.
| Member | Description |
|---|---|
Configuration |
Module configuration |
NestedModules |
Child modules |
Load(ContainerBuilder) |
Register services with Autofac |
</details>
<details> <summary><strong>Module / Module<TConfiguration></strong></summary>
Abstract base classes for Autofac modules.
| Constructor | Description |
|---|---|
Module(TConfiguration, List<IModule>) |
Create with config and nested modules |
Module(IConfiguration) |
Create from IConfiguration section |
| Virtual Method | Description |
|---|---|
OnInitialized() |
Called after construction |
GetKnownDependencies() |
Return hardcoded module dependencies |
Load(ContainerBuilder) |
Register services (override for Autofac registration) |
Note: The Load(IServiceCollection) method is marked as obsolete with error: true to enforce using Autofac's ContainerBuilder.
</details>
<details> <summary><strong>ServiceProviderFactory</strong></summary>
Service provider factory that integrates Baubit.DI module system with Autofac container.
| Constructor | Description |
|---|---|
ServiceProviderFactory(IConfiguration, IComponent[]) |
Create with configuration and components |
ServiceProviderFactory(IServiceProviderFactory<ContainerBuilder>, IConfiguration, IComponent[]) |
Create with custom Autofac factory, configuration, and components |
| Property | Description |
|---|---|
InternalFactory |
The internal Autofac service provider factory |
Modules |
Flattened collection of all loaded modules |
| Method | Description |
|---|---|
Load(ContainerBuilder) |
Load modules into Autofac container (handles both Autofac and standard DI modules) |
UseConfiguredServiceProviderFactory<T>(T) |
Configure host builder with this factory |
Mixed Module Support:
The Load method automatically detects module types:
- Autofac modules (
Baubit.DI.Autofac.IModule) → registered directly withContainerBuilder - Standard DI modules (
Baubit.DI.IModuleonly) → registered withIServiceCollection, then populated into Autofac
</details>
<details> <summary><strong>Configuration</strong></summary>
Abstract base class for Autofac module configurations. Extends Baubit.DI.Configuration.
</details>
For additional API reference on base interfaces and classes (IComponent, Component, ComponentBuilder, ModuleBuilder, etc.), see Baubit.DI API Reference.
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Autofac.Extensions.DependencyInjection (>= 10.0.0)
- Baubit.DI (>= 2025.51.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.