Stax.AutoDependencyInjectionRegistration 4.0.0

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

Attribute Based Dependency Injection for .NET

Version Downloads

Summary

This NuGet library helps to easily register classes without having to add a whole bunch of lines such as service.AddScoped<IService, Service>(). In projects which contain a number of services, this can inflate your code with potentially tens to hundreds of lines.

Auto Dependency Registration makes this easy. All you need is to add services.AutoRegisterDependencies(); within your programs ConfigureServices method and then use one of three registration methods:

  1. Attribute-Based: Add attributes like [RegisterClassAsTransient] above your classes
  2. Interface-Based: Implement marker interfaces like ITransientDependency
  3. Keyed Services (Requires .NET 8+): Use keyed attributes like [RegisterClassAsTransientKeyed("key")] for multiple implementations of the same interface

Dotnet Auto Dependency Registration will take care of the rest without you having to specify assemblies or service name structures for it to pick up.

Why I have written this

While they are a handful of auto DI registration solutions out there, not many of them make it as easy as we were hoping in a project I was working on as we were using a number of projects and didn't want to have to specify a bunch of assemblies and also service name structures to automatically pick up.

I've also been heavily interested in dependency injection and wanted to play around with how it worked and how I could make a lightweight solution to reduce the need to specify in your Program.cs file a whole bunch of services to register. I love the ability to reduce code and believe auto DI registration extension methods are of great use.

How to use

Current solution

Usually your Program.cs file will look something like this:

services.AddScoped<IService, Service>();
services.AddTransient<IService2, Service2>();
services.AddSingleton<IService3, Service3>();
services.AddScoped<IService4, Service4>();
services.AddTransient<IService5, Service5>();
services.AddSingleton<IService6, Service6>();
services.AddScoped<IService7, Service7>();
services.AddTransient<IService8, Service8>();
services.AddSingleton<IService9, Service9>();

etc
How this extension method helps

Using this extension simplifies this greatly.

Within your Program.cs simply add:

services.AutoRegisterDependencies();

Depending on your version of .NET, the containing method example may be:

.NET 5:

public void ConfigureServices(IServiceCollection services)
{
    services.AutoRegisterDependencies();
 }

.NET 6:

builder.services.AutoRegisterDependencies();

From there, you have multiple ways to register your classes:

Attribute-Based Registration

Add attributes on top of your classes:

[RegisterClassAsScoped] - Register as scoped
[RegisterClassAsTransient] - Register as transient
[RegisterClassAsSingleton] - Register as singleton
[RegisterClassAsScopedIgnoreInterface] - Register as scoped but ignore registering the interface
[RegisterClassAsTransientIgnoreInterface] - Register as transient but ignore registering the interface
[RegisterClassAsSingletonIgnoreInterface] - Register as singleton but ignore registering the interface

You are also able to use the base attribute [RegisterClass] which defaults to transient.

Interface-Based Registration

Alternatively, you can implement marker interfaces instead of using attributes:

public class MyService : IMyService, ITransientDependency
{
    // Implementation
}

Available marker interfaces:

  • ITransientDependency - Register as transient
  • IScopedDependency - Register as scoped
  • ISingletonDependency - Register as singleton
  • ITransientDependencyIgnoreInterface - Register as transient but ignore registering the interface
  • IScopedDependencyIgnoreInterface - Register as scoped but ignore registering the interface
  • ISingletonDependencyIgnoreInterface - Register as singleton but ignore registering the interface

Keyed Services (Requires .NET 8+)

For keyed service registration (useful when you have multiple implementations of the same interface), use keyed attributes:

[RegisterClassAsTransientKeyed("ServiceA")]
public class ServiceA : IService
{
    // Implementation
}

[RegisterClassAsTransientKeyed("ServiceB")]
public class ServiceB : IService
{
    // Implementation
}

Available keyed attributes:

  • [RegisterClassAsTransientKeyed("key")] - Register as transient with a key
  • [RegisterClassAsScopedKeyed("key")] - Register as scoped with a key
  • [RegisterClassAsSingletonKeyed("key")] - Register as singleton with a key
  • [RegisterClassAsTransientKeyedIgnoreInterface("key")] - Register as transient with a key but ignore registering the interface
  • [RegisterClassAsScopedKeyedIgnoreInterface("key")] - Register as scoped with a key but ignore registering the interface
  • [RegisterClassAsSingletonKeyedIgnoreInterface("key")] - Register as singleton with a key but ignore registering the interface

To resolve keyed services in .NET 8+:

// Using IKeyedServiceProvider
var serviceA = keyedServiceProvider.GetRequiredKeyedService<IService>("ServiceA");
var serviceB = keyedServiceProvider.GetRequiredKeyedService<IService>("ServiceB");

// Or using [FromKeyedServices] attribute in constructor injection
public class MyController
{
    public MyController([FromKeyedServices("ServiceA")] IService service)
    {
        // service will be the ServiceA implementation
    }
}

You are able to register classes which have interfaces and classes which don't have an interface.

On startup you will see Information logs showing you what classes have been registered and with which ServiceLifetime, in the format of: "ClassName, InterfaceName has been registered as ServiceLifetime." or "ClassName has been registered as ServiceLifetime."

Practical examples

Attribute-Based Registration:

Class.cs

[RegisterClassAsSingleton]
public class Class1 : IClass1
{
    public string Demo()
    {
        return "Hi!";
    }
}

Interface-Based Registration:

Class2.cs

public class Class2 : IClass2, ITransientDependency
{
    public string Demo()
    {
        return "Hi!";
    }
}

Keyed Services (Requires .NET 8+):

ServiceA.cs

[RegisterClassAsTransientKeyed("ServiceA")]
public class ServiceA : IService
{
    public string Process()
    {
        return "Processing with ServiceA";
    }
}

ServiceB.cs

[RegisterClassAsTransientKeyed("ServiceB")]
public class ServiceB : IService
{
    public string Process()
    {
        return "Processing with ServiceB";
    }
}

Class without interface:

Class3.cs

[RegisterClassAsTransient]
public class Class3
{
    public string Demo()
    {
        return "Hi!";
    }
}

Program.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AutoRegisterDependencies();
}

This will cause log entries in console on startup:

Class1, IClass1 has been registered as Singleton
Class2, IClass2 has been registered as Transient
ServiceA, IService has been registered as Transient with key 'ServiceA'
ServiceB, IService has been registered as Transient with key 'ServiceB'
Class3 has been registered as Transient

I also try to circumvent potential mistakes such as:

Class1.cs

[RegisterClassAsTransient]
[RegisterClassAsSingleton]
public class Class1 : IClass1
{
    public string DemoService()
    {
        return "Hi!";
    }
}

In this situation the first attribute will always be used, so the class in this example will be registered as Transient.

Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 is compatible.  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 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. 
.NET Core netcoreapp3.1 is compatible. 
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
4.0.0 226 12/4/2025
3.1.1 4,992 9/17/2023
3.1.0 2,315 4/16/2023
3.0.0 1,787 4/6/2023
2.1.0 8,649 5/26/2022
2.0.1 747 5/1/2022
2.0.0 589 4/26/2022
1.1.0-alpha 341 4/25/2022
1.0.0-alpha 322 4/25/2022