Hasim.Injectify 0.1.6

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

Injectify

Build NuGet NuGet Downloads .NET License

A modular dependency injection system for ASP.NET Core applications that eliminates manual service registration entirely.

Why Injectify?

The Problem

In traditional ASP.NET Core, each new service requires manual registration:

// Every single service needs manual registration 😫
services.AddScoped<IUserService, UserService>();
services.AddScoped<IProductService, ProductService>();
services.AddScoped<IOrderService, OrderService>();
services.AddSingleton<ICacheService, CacheService>();
services.AddTransient<IEmailService, EmailService>();
// ... 50+ more services ...

The Injectify Solution

Implement a marker interface β†’ automatically registered ✨

// Just inherit the marker interface β€” that's it!
public interface IUserService : IAddScoped { }
public class UserService : IUserService { }

public interface ICacheService : IAddSingleton { }
public class CacheService : ICacheService { }

// Everything is auto-discovered and registered with just:
builder.InjectifyApplication();

Concept

Each project in your solution (Application, Core, EF Core, UI, etc.) defines its own module that registers its own dependencies. The host project (UI) discovers and initializes all modules automatically with just two calls:

// Program.cs β€” that's literally all you need
var builder = WebApplication.CreateBuilder(args);
builder.InjectifyApplication();  // Auto-discovers modules + auto-registers all services
var app = builder.Build();
app.InjectifyInitializer();       // Configures app pipeline
app.Run();

No manual service registration. No configuration files. Just implement marker interfaces.

Core Features

Feature Description Impact
πŸš€ Zero Manual Registration Implement marker interfaces β€” services auto-register. No services.Add*() calls needed. Eliminates ~70% of boilerplate
πŸ“¦ Auto-Discovery Recursively scans all assemblies, discovers all IModule implementations automatically One call: builder.InjectifyApplication()
🎯 Marker-based Auto DI IAddSingleton, IAddScoped, IAddTransient on your service β†’ auto-registered by lifetime No more manual .AddScoped<I, T>()
πŸ”„ Module Lifecycle OnInit β†’ ConfigureService β†’ ConfigureApplication β†’ OnStart β†’ OnStop Full control over initialization order
πŸ“Š Dependency Graph Topological sort, cycle detection, dependency validation Fail-fast on misconfiguration
🏷️ Module Metadata [ModuleInfo], [ModuleOrder], [DependsOn] for organization Self-documenting modules
⚑ Conditional Loading Load modules based on environment, config, or custom predicates Feature flags, environment-specific modules

Installation

dotnet add package Injectify

Quick Start

1. Create a module in each project (optional for DI-only services)

using Injectify.Modules;

[ModuleInfo("My Module", "1.0.0", "Description of the module")]
[ModuleOrder(10)]
public class MyModule : BaseInjectifyModule
{
    public override void ConfigureService(IServiceCollection services, IConfiguration configuration)
    {
        services.AddScoped<IMyService, MyService>();
    }

    public override void ConfigureApplication(WebApplication app)
    {
        app.Logger.LogInformation("MyModule initialized");
        app.UseMiddleware<MyMiddleware>();
    }
}

2. In the UI project β€” 2 lines (discovers modules + auto-registers services)

var builder = WebApplication.CreateBuilder(args);
builder.InjectifyApplication();    // Scans all assemblies, discovers all IModule + auto-registers IAddSingleton/IAddScoped/IAddTransient

var app = builder.Build();
app.InjectifyInitializer();            // Calls ConfigureApplication on each module
app.Run();

3. Auto-Register Services with Marker Interfaces (Zero Boilerplate!)

This is the killer feature. Instead of manual registration, just inherit a marker interface:

Traditional approach (verbose):
// Your Program.cs requires THIS for every single service
services.AddScoped<IUserService, UserService>();
services.AddScoped<IProductService, ProductService>();
services.AddScoped<IOrderService, OrderService>();
services.AddSingleton<ICacheService, CacheService>();
services.AddSingleton<IConfigService, ConfigService>();
services.AddTransient<IEmailService, EmailService>();
// ... repeat 50+ times for a real app 😩
Injectify approach (automatic):
using Injectify.Abstractions;

// **That's it.** Just add the marker interface.

// Automatically registered as Scoped
public interface IUserService : IAddScoped { }
public class UserService : IUserService { }

// Automatically registered as Singleton  
public interface ICacheService : IAddSingleton { }
public class CacheService : ICacheService { }

// Automatically registered as Transient
public interface IEmailService : IAddTransient { }
public class EmailService : IEmailService { }

One line in Program.cs does it all:

builder.InjectifyApplication();  // Discovers + auto-registers every IAddSingleton/Scoped/Transient

Benefits:

  • βœ… No boilerplate registration code
  • βœ… Services are self-documenting (lifetime is in the interface name)
  • βœ… New developers can't forget to register a service
  • βœ… Scales from 10 to 1000+ services without friction

4. Module lifecycle

public class MyModule : BaseInjectifyModule
{
    public override void OnInit(IServiceCollection services) { /* before registration */ }
    public override void OnStart(WebApplication app)        { /* after build, before run */ }
    public override void OnStop()                           { /* on shutdown */ }
}

5. Module dependencies

[DependsOn(typeof(CoreModule))]
[DependsOn(typeof(EFCoreModule))]
public class UIModule : BaseInjectifyModule { }

6. Conditional Module Loading

Load modules conditionally based on environment, configuration, or custom logic.

A) Environment-based loading

Load a module only in specific environments (Production, Development, Staging, etc.):

using Injectify.Attributes;
using Injectify.Modules;

// Load only in Production
[ConditionalModule(Environments = "Production")]
public class ProductionAnalyticsModule : BaseInjectifyModule
{
    public override void ConfigureService(IServiceCollection services, IConfiguration configuration)
    {
        services.AddSingleton<IAnalyticsService, ProductionAnalyticsService>();
    }
}

// Load in Production OR Staging (semicolon-separated)
[ConditionalModule(Environments = "Production;Staging")]
public class MonitoringModule : BaseInjectifyModule
{
    public override void ConfigureService(IServiceCollection services, IConfiguration configuration)
    {
        services.AddSingleton<IMonitoringService, MonitoringService>();
    }
}

How it works:

  • Environments = "Production" β†’ loads only when IHostEnvironment.EnvironmentName == "Production"
  • Environments = "Production;Staging" β†’ loads if environment is Production OR Staging
  • Multiple environments separated by ; or ,
B) Configuration-based loading

Load a module if a configuration setting is enabled:

// appsettings.json or appsettings.Development.json
{
  "Features": {
    "Analytics": {
      "Enabled": true
    },
    "Authentication": {
      "OAuth": {
        "Enabled": false
      }
    }
  }
}

// Load only if Features:Analytics:Enabled is true
[ConditionalModule(ConfigurationPath = "Features:Analytics:Enabled")]
public class AnalyticsModule : BaseInjectifyModule
{
    public override void ConfigureService(IServiceCollection services, IConfiguration configuration)
    {
        services.AddSingleton<IAnalyticsEngine, AnalyticsEngine>();
    }
}

// OAuth module loads only if the config key is true
[ConditionalModule(ConfigurationPath = "Features:Authentication:OAuth:Enabled")]
public class OAuthModule : BaseInjectifyModule
{
    public override void ConfigureService(IServiceCollection services, IConfiguration configuration)
    {
        services.AddScoped<IOAuthService, OAuthService>();
    }
}

How it works:

  • ConfigurationPath = "Features:Analytics:Enabled" β†’ loads if config["Features:Analytics:Enabled"] == "true"
  • Configuration value must be a boolean-parseable string ("true" or "false")
  • If the key is missing, the module is skipped
C) Custom predicate loading

Load a module based on custom logic:

using Injectify.Abstractions;
using Injectify.Attributes;
using Injectify.Modules;

// Define a custom condition
public class IsLicensedCondition : IModuleCondition
{
    private readonly ILicenseService _licenseService;
    
    public IsLicensedCondition(ILicenseService licenseService)
    {
        _licenseService = licenseService;
    }

    public async Task<bool> IsSatisfiedAsync()
    {
        // Custom logic: check if premium license is active
        return await _licenseService.IsActivePremiumLicenseAsync();
    }
}

// Load only if the condition is satisfied
[ConditionalModule(ConditionType = typeof(IsLicensedCondition))]
public class PremiumFeaturesModule : BaseInjectifyModule
{
    public override void ConfigureService(IServiceCollection services, IConfiguration configuration)
    {
        services.AddScoped<IAdvancedReportingService, AdvancedReportingService>();
        services.AddScoped<ICustomBrandingService, CustomBrandingService>();
    }
}

How it works:

  • Create a class implementing IModuleCondition
  • Implement IsSatisfiedAsync() β†’ return true to load the module, false to skip it
  • Can be async (e.g., call a database or API to decide)
  • Dependencies are resolved via DI container
D) Hybrid conditions (combine multiple types)

Combine environment + configuration + custom conditions β€” module loads if ANY condition is satisfied (OR logic):

// Load in Production, OR if config enables debug mode, OR if custom condition is satisfied
[ConditionalModule(
    Environments = "Production",
    ConfigurationPath = "Features:DebugMode:Enabled",
    ConditionType = typeof(IsAdminUserCondition)
)]
public class DiagnosticsModule : BaseInjectifyModule
{
    public override void ConfigureService(IServiceCollection services, IConfiguration configuration)
    {
        services.AddSingleton<IDiagnosticsService, DiagnosticsService>();
    }
}

This module loads if:

  • Environment is Production, OR
  • Config key "Features:DebugMode:Enabled" is true, OR
  • Custom condition IsAdminUserCondition is satisfied
Complete example: Environment + Feature flags
// appsettings.Development.json
{
  "Features": {
    "Development": {
      "HotReload": true
    }
  }
}

// In your module
[ConditionalModule(
    Environments = "Development",
    ConfigurationPath = "Features:Development:HotReload"
)]
public class HotReloadModule : BaseInjectifyModule
{
    public override void ConfigureApplication(WebApplication app)
    {
        app.Logger.LogInformation("Hot reload enabled in Development");
        // Configure hot reload middleware
    }
}

Performance Benchmarks

Baseline performance metrics measured with BenchmarkDotNet on .NET 8.0 (Intel Core i5-6300U).

Key Metrics

Scenario Time Memory
Discovery + Registration (current assembly) 5.67 ΞΌs 4.28 KB
Discovery + Registration (Injectify assembly) 9.52 ΞΌs 4.83 KB
Singleton Registration 3.83 ΞΌs 3.78 KB
Scoped Registration 4.96 ΞΌs 3.78 KB
Transient Registration 4.38 ΞΌs 3.78 KB
Single Assembly Startup 5.34 ΞΌs 4.28 KB
Multiple Assemblies Startup 13.13 ΞΌs 5.60 KB

Injectify vs Manual Registration

Method Time Memory Overhead
Injectify Auto-Registration 5.11 ΞΌs 4.28 KB +28% time
Manual Registration 3.98 ΞΌs 3.95 KB baseline

Analysis: Injectify's auto-discovery and registration adds ~1.1 microseconds of overhead per operation, with slightly higher memory footprint (330 bytes). For typical applications, this represents negligible performance impact compared to the boilerplate elimination benefit.

Packages

Package Description
Injectify Module system with DI registration, pipeline config, and module lifecycle

Project structure

Injectify/
β”œβ”€β”€ Abstractions/          # Public contracts: IModule, IModuleLifecycle, IModuleLoader, DI markers
β”œβ”€β”€ Attributes/            # [DependsOn], [ModuleInfo], [ModuleOrder]
β”œβ”€β”€ Exceptions/            # InjectifyException, DependencyCycleException
β”œβ”€β”€ Extensions/            # Fluent DI extensions (InjectifyApplication, InjectifyInitializer, DependencyInjectionExtensions)
β”œβ”€β”€ Modules/               # BaseInjectifyModule
β”œβ”€β”€ Setup/                 # ModuleLoader, ModuleDependencySorter (assembly scanning, topological sort)
└── Injectify.Tests/       # Unit tests (xUnit)

Documentation

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on Hasim.Injectify:

Package Downloads
Hasim.Auditify

A lightweight, pluggable audit-trail library for EF Core 8+. Automatically captures entity changes (Added/Modified/Deleted), supports sensitive data masking, soft-delete patterns, and timestamp tracking.

Hasim.EntityFrameworkCore

A customizable ASP.NET Core Identity entities library providing reusable base identity models and common abstractions for modern .NET applications.

Hasim.Infrastructure

Todo Description.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.6 134 9/21/2026
0.1.5 100 9/21/2026
0.1.4 170 8/28/2026
0.1.3 115 8/27/2026
0.1.2 334 7/30/2026
0.1.1 241 7/30/2026
0.1.0 177 7/30/2026