InzSoftwares.NetDynamicModuleLoader.Abstractions 1.0.0

dotnet add package InzSoftwares.NetDynamicModuleLoader.Abstractions --version 1.0.0
                    
NuGet\Install-Package InzSoftwares.NetDynamicModuleLoader.Abstractions -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="InzSoftwares.NetDynamicModuleLoader.Abstractions" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="InzSoftwares.NetDynamicModuleLoader.Abstractions" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="InzSoftwares.NetDynamicModuleLoader.Abstractions" />
                    
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 InzSoftwares.NetDynamicModuleLoader.Abstractions --version 1.0.0
                    
#r "nuget: InzSoftwares.NetDynamicModuleLoader.Abstractions, 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 InzSoftwares.NetDynamicModuleLoader.Abstractions@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=InzSoftwares.NetDynamicModuleLoader.Abstractions&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=InzSoftwares.NetDynamicModuleLoader.Abstractions&version=1.0.0
                    
Install as a Cake Tool

InzDynamicModuleLoader

InzDynamicModuleLoader is a .NET 9.0 library that enables plugin-based architecture by loading modules at startup time. This allows for better separation of concerns, module isolation, and flexible infrastructure switching while maintaining clean architecture boundaries.

Table of Contents

Features

  • Dynamic Module Loading: Load modules at runtime based on configuration
  • Plugin Architecture: Create extensible applications with modular functionality
  • Easy Integration: Simple setup with .NET's built-in dependency injection
  • Dependency Management: Automatic resolution of module-specific dependencies
  • Configuration-Driven: Control which modules load through configuration files
  • Development & Production: Works seamlessly in both environments

Prerequisites

  • .NET 9.0 or higher

How to Use

1. Install the Package

Add the Inz Dynamic Module Loader to your startup project:

dotnet add package InzSoftwares.NetDynamicModuleLoader

2. Configure Build Targets

Create a Directory.Build.targets file in your solution root directory with this content. This ensures all module dependencies are properly copied:


<Project>
    <PropertyGroup Condition="'$(IsModuleProject)' == 'true'">
        
        <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
        
        <GenerateDependencyFile>true</GenerateDependencyFile>
    </PropertyGroup>

    
    <Target Name="DeployModuleToUnifiedFolder" AfterTargets="Build" Condition="'$(IsModuleProject)' == 'true'">
        <PropertyGroup>
            <UnifiedModulePath>$(MSBuildThisFileDirectory)BuiltModules/$(MSBuildProjectName)/</UnifiedModulePath>
        </PropertyGroup>

        <ItemGroup>
            <ModuleFiles Include="$(OutputPath)**/*.*"/>
        </ItemGroup>

        <Message Text="[Module Deployment] Copying $(MSBuildProjectName) to $(UnifiedModulePath)" Importance="High"/>

        <Copy SourceFiles="@(ModuleFiles)"
              DestinationFolder="$(UnifiedModulePath)%(RecursiveDir)"
              SkipUnchangedFiles="true"/>
    </Target>
</Project>

This configuration ensures each dynamically loaded module includes all its dependencies and the deps.json file. The custom target creates a dedicated BuiltModules directory in the solution directory where each dynamically loaded module's dependencies can be found and resolved correctly.

For more details about this file and its purpose, see the Directory.Build.targets Documentation.

3. Create a Module Project

  1. Create a new .NET Class Library project
  2. In the .csproj file, add the IsModuleProject property:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFramework>net9.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        
        <IsModuleProject>true</IsModuleProject>
    </PropertyGroup>

</Project>

4. Implement Your Module

In your module project, create a class that implements the IAmModule interface:

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using InzDynamicLoader.Core;

public class MyExampleModule : IAmModule
{
    public IServiceCollection RegisterServices(IServiceCollection services, IConfiguration configuration)
    {
        // Register your module's services here
        // Example: services.AddScoped<IMyService, MyServiceImplementation>();

        return services;
    }

    public IServiceProvider InitializeServices(IServiceProvider services, IConfiguration configuration)
    {
        // Initialize services after registration (optional)
        // Example: Initialize database connections, event handlers, etc.

        return services;
    }
}

5. Configure Modules

In your main application's appsettings.json, specify which modules to load:

{
  "Modules": [
    "MyExampleModule",
    "AnotherModule"
  ]
}

6. Register and Initialize Modules

In your main application's Program.cs (or Startup.cs), register and initialize the modules:

using InzDynamicLoader.Core;

var builder = WebApplication.CreateBuilder(args);

// Register modules and their services
builder.Services.RegisterModules(builder.Configuration);

var app = builder.Build();

// Initialize modules after services are registered
app.Services.InitializeModules(builder.Configuration);

// Continue with your application setup
app.Run();

Project Structure

After setup, your solution will have this structure:

YourSolution/
├── MainApplication/          # Your main application
├── MyExampleModule/          # First module project
├── MyOtherModule/            # Second module project
├── Directory.Build.targets   # Build configuration
├── Directory.Packages.props  # Centralized package versions
└── BuiltModules/             # Automatically created - contains compiled modules
    ├── MyExampleModule/
    │   ├── MyExampleModule.dll
    │   ├── MyExampleModule.deps.json
    │   └── Dependencies...
    └── MyOtherModule/
        ├── MyOtherModule.dll
        ├── MyOtherModule.deps.json
        └── Dependencies...

Managing Dependencies

When working with multiple modules, you may encounter the "Diamond Dependency" problem. This occurs when different modules require the same dependency but at different versions. For example:

  • Module A requires Newtonsoft.Json v13
  • Module B requires Newtonsoft.Json v9
  • At runtime, only one version can be loaded, which may cause compatibility issues

To solve this problem and ensure version consistency across all modules, create a Directory.Packages.props file in your solution root. This file enables Central Package Management, which defines package versions in one central location:


<Project>
    <PropertyGroup>
        <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
    </PropertyGroup>

    <ItemGroup>
        
        <PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0"/>
        <PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0"/>
        <PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.0"/>
        
    </ItemGroup>
</Project>

When using this approach, reference packages without specifying versions in your project files:


<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions"/>

For more information about this file and its content, see the Directory.Packages.props Documentation.

IAmModule Interface Explained

The IAmModule interface has two methods:

  • RegisterServices: Called first, registers services with the dependency injection container
  • InitializeServices: Called after registration, allows for service initialization and configuration

Example Implementation

The project includes a comprehensive example that demonstrates the dynamic loading capabilities of the InzDynamicModuleLoader system. The example showcases a real-world scenario where database infrastructure can be switched at startup without code changes.

The example includes:

  • Multiple database provider implementations (MySQL and PostgreSQL)
  • Core shared components with contracts and data models
  • Common EF Core repository patterns
  • Runtime switching between database providers based on configuration
  • Clean separation of concerns between modules

The example uses modules with the Example. prefix to demonstrate:

  • Example.Module.Common - Contains shared contracts, entities, and configurations
  • Example.Module.EFCore.MySQL - MySQL-specific implementation
  • Example.Module.EFCore.PostgreSQL - PostgreSQL-specific implementation
  • Example.Module.EFCore.Repositories - Repository implementations
  • Example.Module.WebStartup - Web application startup project

This architecture demonstrates how to build flexible applications where infrastructure concerns can be swapped out dynamically, maintaining clean separation of concerns while enabling maximum flexibility.

For step-by-step instructions on how to run and understand the example, see the Example Breakdown documentation.

Troubleshooting

Problem: Module dependencies not found

  • Solution: Ensure IsModuleProject=true is set in your module project

Problem: Type conflicts between modules

  • Solution: Use Directory.Packages.props to ensure version consistency

Problem: Module not loading

  • Solution: Check that the module name in appsettings.json matches the assembly name exactly

Learn More

For detailed technical information about how the module loading system works, check out the Module System Architecture documentation.

Contributing

Contributions are welcome! Feel free to submit issues or pull requests to improve this library.

License

This project is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  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. 
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 InzSoftwares.NetDynamicModuleLoader.Abstractions:

Package Downloads
InzSoftwares.NetDynamicModuleLoader

A .NET 9.0 library that enables plugin-based architecture by loading modules at startup time. This allows for better separation of concerns, module isolation, and flexible modules switching based on configuration while maintaining clean architecture boundaries.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 289 12/19/2025