JZen.AutoInject 2.0.1

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

๐Ÿš€ AutoInject

.NET 8.0 License: MIT NuGet

๐ŸŽ‰ NEW v2.0: Smart Auto-Registration!
Stop writing constructor injection boilerplate! ๐Ÿ›‘
AutoInject automatically discovers and registers your dependencies using inheritance - zero manual registration needed!

๐Ÿง  Smart Auto-Registration via InjectBase

The future of dependency injection is here! No more manual registration:

// Program.cs - Just this! ๐ŸŽฏ
var builder = WebApplication.CreateBuilder(args);
// No special setup needed for InjectBase! Factory auto-configures!

var app = builder.Build();
app.UseFactoryDependencyInjection(); // Configure AutoInject Factory
app.Run();

// Your service - Zero configuration needed! โœจ
public class UserService : InjectBase
{
    [Injectable] private readonly IUserRepository? _repository;     // Auto-found!
    [Injectable] private readonly IEmailService? _emailService;     // Auto-registered!
    
    public async Task CreateUserAsync(string name)
    {
        var user = new User { Name = name };
        await _repository!.SaveAsync(user);           // Works automatically!
        _emailService!.SendWelcomeEmail(user);        // No setup required!
    }
}

๐ŸŽฏ How Smart Auto-Registration Works:

  1. ๐Ÿ” Inherits from InjectBase - Automatic dependency discovery
  2. ๐Ÿ“ Auto-registers implementations as Scoped services on first use
  3. ๐Ÿ’‰ Injects dependencies instantly using [Injectable] attributes
  4. ๐Ÿš€ Caches mappings for blazing-fast performance
  5. ๐Ÿงน Manages scoping and disposal automatically

๐Ÿ†š Before vs After:

Before (Manual Hell) After (InjectBase Auto-Registration)
50+ lines of registration Zero registration needed
Manual interface mapping Automatic discovery
Assembly scanning setup Just inherit InjectBase
Startup performance hit Lazy, on-demand loading
Maintenance nightmare Self-maintaining

๐Ÿ“‹ Two Ways to Use AutoInject

Simply inherit from InjectBase - no registration needed:

// Program.cs - Minimal setup
var app = builder.Build();
app.UseFactoryDependencyInjection();
app.Run();

// Your service - Just inherit and use!
public class OrderService : InjectBase
{
    [Injectable] private readonly IOrderRepository? _repository;
    [Injectable] private readonly IEmailService? _emailService;
    
    public async Task ProcessOrderAsync(Order order)
    {
        await _repository!.SaveAsync(order);
        _emailService!.SendConfirmation(order);
    }
}

๐Ÿ”ง Method 2: [AutoInject] Attribute (For Existing Classes)

For classes you can't modify to inherit from InjectBase:

// Program.cs - Register classes with [AutoInject]
builder.Services.AddAutoInjectClasses(); // Scans for [AutoInject] classes
var app = builder.Build();
app.UseFactoryDependencyInjection();
app.Run();

// Your existing class
[AutoInject]
public class LegacyService
{
    [Injectable] private readonly IRepository? _repository;
    
    public void DoSomething()
    {
        // Factory.InjectDependencies(this) called automatically
        _repository!.Save(data);
    }
}

๐Ÿš€ Quick Start

1. Install the Package

dotnet add package JZen.AutoInject

2. Configure (One Line!)

For InjectBase classes (recommended):

var builder = WebApplication.CreateBuilder(args);
// No services registration needed!

var app = builder.Build();
app.UseFactoryDependencyInjection(); // ๐Ÿš€ Factory configured!
app.Run();

For [AutoInject] classes:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAutoInjectClasses(); // ๐ŸŽฏ Register classes with [AutoInject]

var app = builder.Build();
app.UseFactoryDependencyInjection(); // ๐Ÿš€ Factory configured!
app.Run();

3. Use in Your Classes

Option A: InjectBase (Zero Setup)

public class ProductService : InjectBase
{
    [Injectable] private readonly IProductRepository? _repository;
    [Injectable] private readonly ICacheService? _cache;
    
    public async Task<Product> GetProductAsync(int id)
    {
        _logger.LogInformation("Getting product {Id}", id);
        
        var cached = _cache!.Get<Product>($"product_{id}");
        if (cached != null) return cached;
        
        var product = await _repository!.GetByIdAsync(id);
        _cache.Set($"product_{id}", product);
        
        return product;
    }
}

Option B: [AutoInject] Attribute

[AutoInject]
public class ProductService
{
    [Injectable] private readonly IProductRepository? _repository;
    [Injectable] private readonly ICacheService? _cache;
    
    // Dependencies injected automatically when created via DI container
}

That's it! No manual registration needed! ๐ŸŽ‰

๐ŸŽ›๏ธ Features

๐Ÿง  Smart Auto-Registration

  • Zero configuration - InjectBase automatically finds implementations
  • On-demand discovery - Only registers what you actually use
  • Performance optimized - Caches mappings for speed
  • Cross-assembly support - Works with any loaded assembly

๐ŸŽฏ Two Integration Patterns

  • InjectBase: Automatic injection on construction (recommended)
  • [AutoInject]: Factory-based injection for existing classes

๐Ÿชต Built-in Logging

  • Automatic ILogger injection via InjectBase
  • Type-safe logger instances
  • Zero configuration

โœ… Scoped Management

  • HTTP request scoping
  • Automatic disposal
  • Thread-safe operations

โœ… ASP.NET Core Integration

  • Works with existing DI container
  • Middleware support
  • Controller injection

โœ… Backward Compatibility

  • Mix with manual registrations
  • Existing code keeps working
  • Gradual migration support

๐Ÿ“‹ Usage Examples

Basic Service with InjectBase

public class EmailService : InjectBase
{
    [Injectable] private readonly IEmailProvider? _provider;
    [Injectable] private readonly ITemplateEngine? _templates;
    
    public async Task SendAsync(string to, string subject, string body)
    {
        _logger.LogInformation("Sending email to {To}", to);
        
        var template = _templates!.Render(body);
        await _provider!.SendAsync(to, subject, template);
    }
}

Controller Integration

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    private readonly UserService _userService = new(); // InjectBase auto-injects
    
    [HttpPost]
    public async Task<IActionResult> CreateUser(CreateUserRequest request)
    {
        var user = await _userService.CreateUserAsync(request.Name);
        return Ok(user);
    }
}

Background Service

public class OrderProcessingService : BackgroundService, InjectBase
{
    [Injectable] private readonly IOrderRepository? _orders;
    [Injectable] private readonly IPaymentService? _payments;
    
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var pendingOrders = await _orders!.GetPendingAsync();
            
            foreach (var order in pendingOrders)
            {
                await _payments!.ProcessAsync(order);
                _logger.LogInformation("Processed order {OrderId}", order.Id);
            }
            
            await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
        }
    }
}

๐Ÿ”ง Advanced Configuration

Mixed Registration

// Program.cs - Mix manual and auto registration
builder.Services.AddScoped<ISpecialService, CustomImplementation>(); // Manual registration
// InjectBase classes will auto-register their dependencies

public class MyService : InjectBase
{
    [Injectable] private readonly ISpecialService? _special;      // Uses manual registration
    [Injectable] private readonly IRegularService? _regular;     // Auto-registered
}

Non-Web Applications

// For console apps, background services, etc.
var services = new ServiceCollection();
services.AddLogging();

var serviceProvider = services.BuildServiceProvider();
Factory.Configure(serviceProvider);

// Now you can use InjectBase classes
var myService = new MyService(); // Dependencies auto-injected

Manual Injection

public class LegacyClass
{
    [Injectable] private readonly IRepository? _repository;
    
    public LegacyClass()
    {
        Factory.InjectDependencies(this); // Manual injection
    }
}

Custom Assembly Scanning for [AutoInject]

// Scan specific assemblies for [AutoInject] classes
builder.Services.AddAutoInjectClasses(Assembly.GetExecutingAssembly());
builder.Services.AddAutoInjectClasses(typeof(SomeExternalClass).Assembly);

// Or scan multiple assemblies
var assemblies = new[] { Assembly.GetExecutingAssembly(), typeof(ExternalService).Assembly };
builder.Services.AddAutoInjectClasses(assemblies);

๐ŸŽฏ When to Use AutoInject

โœ… Perfect For:

  • Rapid prototyping - Get up and running fast
  • Clean architecture - Focus on business logic
  • Large applications - Reduce boilerplate significantly
  • Convention over configuration - Sensible defaults

โš ๏ธ Consider Alternatives When:

  • You need multiple implementations of the same interface
  • Complex lifetime management requirements (Singleton, custom scopes)
  • Performance-critical applications with strict DI requirements
  • You prefer explicit registration for all services

๐Ÿ”„ Migration Guide

๐ŸŽ‰ Upgrading to v2.0

v2.0 is 100% backward compatible. Your existing code continues to work unchanged.

Recommended new setup:

// Program.cs - v2.0 InjectBase (Zero registration!)
var app = builder.Build();
app.UseFactoryDependencyInjection(); // Just this line!
app.Run();

// Your service - Just inherit InjectBase
public class MyService : InjectBase
{
    [Injectable] private readonly IRepository? _repository; // Auto-discovered!
}

For [AutoInject] classes:

// Program.cs - v2.0 with [AutoInject] support
builder.Services.AddAutoInjectClasses(); // Register [AutoInject] classes
app.UseFactoryDependencyInjection();

โš ๏ธ Obsolete Methods

The following methods are now obsolete and will be removed in v3.0:

// โŒ Obsolete - Don't use these anymore
services.AddInjectBaseClasses(assembly);
services.AddInjectBaseClasses(assemblies);  
services.AddInjectBaseClasses();

Migration is simple:

// Before - Manual registration (obsolete)
services.AddInjectBaseClasses(Assembly.GetExecutingAssembly());

// After - No registration needed for InjectBase!
// Just use: app.UseFactoryDependencyInjection();

// OR for [AutoInject] classes:
services.AddAutoInjectClasses(); // Replaces AddInjectBaseClasses

From Constructor Injection

// Before
public class OrderService
{
    private readonly IRepository _repo;
    private readonly IEmailService _email;
    
    public OrderService(IRepository repo, IEmailService email)
    {
        _repo = repo;
        _email = email;
    }
}

// After
public class OrderService : InjectBase
{
    [Injectable] private readonly IRepository? _repo;
    [Injectable] private readonly IEmailService? _email;
}

From Manual DI Registration

// Before - Program.cs (50+ lines)
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IEmailService, EmailService>();
services.AddScoped<INotificationService, NotificationService>();
// ... dozens more registrations

// After - Program.cs (1 line)
app.UseFactoryDependencyInjection(); // InjectBase auto-handles everything!

๐Ÿ“Š Performance

  • Startup: Minimal overhead, lazy discovery
  • Runtime: Cached type mappings for fast resolution
  • Memory: Efficient scoping and disposal
  • Throughput: Comparable to native DI container

๐Ÿค Contributing

We welcome contributions! Please see our Contributing Guide for details.

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ™ Acknowledgments

  • Inspired by the need for cleaner dependency injection in .NET
  • Built on top of Microsoft.Extensions.DependencyInjection
  • Community feedback and contributions

Made with โค๏ธ for the .NET community

โญ Star this repo if you find it useful!

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

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.1 150 6/3/2025
2.0.0 143 6/3/2025
1.1.0 144 6/3/2025
1.0.0 150 5/29/2025

📚 AutoInject v2.0.1 - Documentation Fix! Corrected README with accurate API methods: Use app.UseFactoryDependencyInjection() (not UseAutoInject), and AddAutoInjectClasses() for [AutoInject] attribute classes. InjectBase inheritance requires zero configuration. All code examples now reflect the actual working API.