{"id":16989926,"url":"https://github.com/x39/x39.hosting.modularization","last_synced_at":"2026-02-27T01:04:38.592Z","repository":{"id":74149861,"uuid":"522163640","full_name":"X39/X39.Hosting.Modularization","owner":"X39","description":"This is a .NET library that enables dynamic loading and unloading of modular plugins. It supports runtime dependency resolution, module configuration via module.json, and integrates with the dependency injection system.","archived":false,"fork":false,"pushed_at":"2025-12-21T18:06:16.000Z","size":139,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-12T18:25:30.828Z","etag":null,"topics":["csharp","dependency-injection","dotnet","hostbuilder","module-system","plugin-system"],"latest_commit_sha":null,"homepage":"https://www.nuget.org/packages/X39.Hosting.Modularization","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/X39.png","metadata":{"files":{"readme":"ReadMe.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-08-07T09:01:53.000Z","updated_at":"2025-12-21T18:06:19.000Z","dependencies_parsed_at":"2023-09-21T20:27:35.103Z","dependency_job_id":"246857d1-6384-428f-abcf-f7aaa0c05752","html_url":"https://github.com/X39/X39.Hosting.Modularization","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/X39/X39.Hosting.Modularization","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/X39%2FX39.Hosting.Modularization","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/X39%2FX39.Hosting.Modularization/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/X39%2FX39.Hosting.Modularization/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/X39%2FX39.Hosting.Modularization/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/X39","download_url":"https://codeload.github.com/X39/X39.Hosting.Modularization/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/X39%2FX39.Hosting.Modularization/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29879920,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-26T23:51:21.483Z","status":"ssl_error","status_checked_at":"2026-02-26T23:50:46.793Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","dependency-injection","dotnet","hostbuilder","module-system","plugin-system"],"created_at":"2024-10-14T03:08:28.278Z","updated_at":"2026-02-27T01:04:38.584Z","avatar_url":"https://github.com/X39.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- TOC --\u003e\n  * [Semantic Versioning](#semantic-versioning)\n* [Overview](#overview)\n  * [Installing the Template](#installing-the-template)\n  * [Quickstart](#quickstart)\n  * [Features](#features)\n  * [FAQ](#faq)\n    * [Why can't I replace or delete a library after unloading my module?](#why-cant-i-replace-or-delete-a-library-after-unloading-my-module)\n    * [Why doesn't my renamed assembly load?](#why-doesnt-my-renamed-assembly-load)\n    * [Why aren't my dependencies available in the module?](#why-arent-my-dependencies-available-in-the-module)\n    * [How can I get the GUID of the module without injecting the `ModuleLoader`?](#how-can-i-get-the-guid-of-the-module-without-injecting-the-moduleloader)\n    * [Why is there no `AddModularization(this IServiceCollection)` extension method?](#why-is-there-no-addmodularizationthis-iservicecollection-extension-method)\n  * [Examples](#examples)\n* [License](#license)\n* [Contributing](#contributing)\n  * [Code of Conduct](#code-of-conduct)\n  * [Contributors Agreement](#contributors-agreement)\n\u003c!-- TOC --\u003e\n\n## Semantic Versioning\n\nThis library follows the principles of [Semantic Versioning](https://semver.org/). This means that version numbers and\nthe way they change convey meaning about the underlying changes in the library. For example, if a minor version number\nchanges (e.g., 1.1 to 1.2), this indicates that new features have been added in a backwards-compatible manner.\n\n# Overview\n\nThe `X39.Hosting.Modularization` library simplifies adding modular functionality (plugins) to .NET applications. By\nleveraging this library, you can dynamically load, unload, and manage modules that extend the core features of your\nsoftware.\n\n## Installing the Template\n\nThe library provides a project template to streamline setup. To install the template via the .NET CLI, run:\n\n```bash\ndotnet new install X39.Hosting.Modularization.TemplatePackage\n```\n\n## Quickstart\n\nTo quickly get started, follow the example below:\n\n```csharp\n// Program.cs\nvar hostBuilder = Host.CreateDefaultBuilder(args);\nhostBuilder.UseModularization(Path.GetFullPath(\"Modules\"));\nhostBuilder.ConfigureServices(collection =\u003e collection.AddHostedService\u003cWorker\u003e());\nvar host = hostBuilder.Build();\nhost.Run();\n\n// Worker.cs\npublic class Worker : BackgroundService\n{\n    protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n    {\n        await _moduleLoader.LoadAllAsync(stoppingToken);\n    }\n}\n```\n\n\u003e **Note**: The plugin directories are defined once during application startup.\n\n\u003e **Note**: There are additional overloads and ways to load modules, this is just one of them.\n\u003e Follow the code-documentation for further information.\n\n## Features\n\n- **Runtime Module Loading**  \n  Dynamically load plugin-based assemblies at runtime.\n  Each module can extend your application's functionality.\n\n- **Module Configuration via `module.json`**  \n  Every module has a `module.json` file, where you can define a unique module GUID,\n  licenses, and other important metadata.\n\n- **Automatic Dependency Resolution**  \n  Modules can declare dependencies (on other modules) in the `module.json` file,\n  and the library will automatically handle these dependencies during module loading.\n\n- **Module Unloading**  \n  To unload a module, simply call `Unload()` on the `ModuleContext`.\n  Keep in mind that any references to types from the module will prevent it from fully unloading.\n\n- **Clear Module Entry Point**  \n  Every module must implement the `IModuleMain` interface once,\n  similar to the `Main()` method in a standard .NET application.\n  This provides a clear entry point with dependency injection support.\n\n- **Dependency Injection Support**  \n  Modules are instantiated using the `IServiceProvider` via dependency injection.\n  Modules can also register services that other dependent modules can consume.\n\n- **Tiered Dependency Injection**  \n  Every module has it's very own `IServiceCollection`, resolving to both the parented dependencies and\n  it's very own services.\n  This allows building DI chains across modules, which are properly handled.\n\n## FAQ\n\n### Why can't I replace or delete a library after unloading my module?\n\nUnloading a module works, but the .NET CLR doesn’t support fully \"unloading\" assemblies in all\nsituations.\nIf any part of your application holds a reference to a type from the unloaded module\n(e.g., via caching), the assembly will remain in memory,\npreventing you from replacing or deleting it.\n\nTo troubleshoot this,\ncheck for objects still in memory that may be holding references to the module\n(e.g., in Rider via the Memory Tab, or Visual Studio's .NET object snapshot tools).\nCaching is a common culprit here.\n\n### Why doesn't my renamed assembly load?\n\nThe library does not automatically detect the module entrypoint for security reasons.\nIf you rename an assembly, you must also update the `module.json` file to reflect the\nnew assembly name.\n\n### Why aren't my dependencies available in the module?\n\nWhile every module has it's very own Dependency Injection Container, the actual resolution is tiered.\nCheck your dependency chain for whether you actually have the service injected.\nRemember: Dependencies may be set in any tiered part and to make ModuleB depend on ModuleA, you have to define that\nin your `module-info.json`\n\n```csharp\npublic sealed class ModuleMain : IModuleMain\n{\n    private readonly IMyFancyService _myFancyService;\n    \n    public ModuleMain(IMyFancyService myFancyService)\n    {\n        _myFancyService = myFancyService;\n    }\n    \n    public ValueTask ConfigureServicesAsync(\n        IServiceCollection serviceCollection,\n        CancellationToken cancellationToken\n    )\n    {\n        serviceCollection.AddSingleton(_myFancyService);\n        return ValueTask.CompletedTask;\n    }\n    \n    // [...]\n}\n```\n\n### How can I get the GUID of the module without injecting the `ModuleLoader`?\n\nYes, you can access the module's GUID, as specified in the `module.json`,\nby injecting the `ModuleGuid` class from the\n`X39.Hosting.Modularization.Abstraction` namespace:\n\n```csharp\npublic sealed class ModuleMain : IModuleMain\n{\n    private readonly Guid _moduleGuid;\n    \n    public ModuleMain(ModuleGuid moduleGuid)\n    {\n        _moduleGuid = moduleGuid;\n    }\n    \n    // [...]\n}\n```\n\n### Why is there no `AddModularization(this IServiceCollection)` extension method?\n\nIt was actively decided against this to not add such an extension method, to prevent\n\"child\" modules from calling this on their respective `IServiceCollection`.\n\nIf you must have a `IServiceCollection` overload, please create one your own.\nYou may call `X39.Hosting.Modularization.ServiceCollectionExtensions.AddModularizationSupport(...)`\nusing reflection to archive that.\n\n## Examples\n\nSample projects are available in the\n[GitHub repository](https://github.com/X39/X39.Hosting.Modularization/tree/master/samples).\nThese examples demonstrate how to build and extend applications using the `Modularization` library.\nIf you feel like there are some examples missing, feel free to create tickets or supply your own.\n\n# License\n\nThe entire project, excluding the DotNet template, is released under\nthe [LGPLv3](https://www.gnu.org/licenses/lgpl-3.0.html) license.\nThe DotNet template, along with all generated code from it, is considered public domain and may be used or licensed\nfreely as per your needs.\n\n# Contributing\n\nContributions are welcome!\nPlease submit a pull request or create a discussion to discuss any changes you wish to make.\n\n## Code of Conduct\n\nBe excellent to each other.\n\n## Contributors Agreement\n\nFirst of all, thank you for your interest in contributing to this project!\nPlease add yourself to the list of contributors in the [CONTRIBUTORS](CONTRIBUTORS.md) file when submitting your\nfirst pull request.\nAlso, please always add the following to your pull request:\n\n```\nBy contributing to this project, you agree to the following terms:\n- You grant me and any other person who receives a copy of this project the right to use your contribution under the\n  terms of the GNU Lesser General Public License v3.0.\n- You grant me and any other person who receives a copy of this project the right to relicense your contribution under\n  any other license.\n- You grant me and any other person who receives a copy of this project the right to change your contribution.\n- You waive your right to your contribution and transfer all rights to me and every user of this project.\n- You agree that your contribution is free of any third-party rights.\n- You agree that your contribution is given without any compensation.\n- You agree that I may remove your contribution at any time for any reason.\n- You confirm that you have the right to grant the above rights and that you are not violating any third-party rights\n  by granting these rights.\n- You confirm that your contribution is not subject to any license agreement or other agreement or obligation, which\n  conflicts with the above terms.\n```\n\nThis is necessary to ensure that this project can be licensed under the GNU Lesser General Public License v3.0 and\nthat a license change is possible in the future if necessary (e.g., to a more permissive license).\nIt also ensures that I can remove your contribution if necessary (e.g., because it violates third-party rights) and\nthat I can change your contribution if necessary (e.g., to fix a typo, change implementation details, or improve\nperformance).\nIt also shields me and every user of this project from any liability regarding your contribution by deflecting any\npotential liability caused by your contribution to you (e.g., if your contribution violates the rights of your\nemployer).\nFeel free to discuss this agreement in the discussions section of this repository, I am open to changes here (as long as\nthey do not open me or any other user of this project to any liability due to a **malicious contribution**).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fx39%2Fx39.hosting.modularization","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fx39%2Fx39.hosting.modularization","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fx39%2Fx39.hosting.modularization/lists"}