A dependency injection automation library for .NET that simplifies service registration using attributes. Automatically discovers and registers services decorated with the [AutoRegister] attribute, supporting various lifetimes and registration strategies.
$ dotnet add package Skywithin.AutoRegisterA dependency injection automation library for .NET that simplifies service registration using attributes. This library automatically discovers and registers services decorated with the [AutoRegister] attribute, supporting various lifetimes and registration strategies.
[AutoRegister] attributeScoped, Transient, and Singleton lifetimesIDisposabledotnet add package Skywithin.AutoRegister
using Skywithin.AutoRegister.DI;
[AutoRegister(Lifetime.Scoped, RegisterAs.Interface)]
public class UserService : IUserService
{
// Implementation...
}
builder.Services.AddAutoRegisteredServicesFromAssembly(
typeof(UserService).Assembly
);
When a class implements multiple interfaces, you can explicitly specify which interface to use:
[AutoRegister(Lifetime.Scoped, RegisterAs.Interface, typeof(IUserService))]
public class UserService : IDisposable, IUserService, IAsyncDisposable
{
// Will register as IUserService, not IDisposable
}
Some developers have concerns that using the [AutoRegister] attribute violates SOLID principles, particularly the Single Responsibility Principle (SRP). However, it's important to understand the design philosophy:
The attribute is a marker, not the registration logic itself.
[AutoRegister] attribute serves as a declarative marker that indicates a class should be registeredAddAutoRegisteredServicesFromAssembly method// The attribute is just metadata - it doesn't execute registration logic
[AutoRegister(Lifetime.Scoped, RegisterAs.Interface)]
public class UserService : IUserService
{
// This class has one responsibility: user business logic
// The registration happens elsewhere, separately
}
Acknowledged concern: Using the [AutoRegister] attribute does create a dependency between your domain/application code and the dependency injection infrastructure.
The trade-off:
When this matters:
AutoRegister.DI is designed with a pragmatic approach that prioritizes developer productivity and maintainability:
Works well for:
Consider alternatives for:
Use AutoRegister.DI when:
Consider manual registration when:
Hybrid approach:
You can also use a hybrid approach—use [AutoRegister] for most services, but manually register services that have special requirements or need explicit control:
// Use AutoRegister for standard services
services.AddAutoRegisteredServicesFromAssembly(
typeof(Application.AssemblyReference).Assembly
);
// Manually register services with special requirements
services.AddScoped<ISpecialService>(sp =>
new SpecialService(sp.GetRequiredService<IOptions<SpecialConfig>>()));
AutoRegister.DI makes a pragmatic trade-off between architectural purity and developer convenience. It's designed to work well for most projects, but acknowledges that for very large projects with strict architectural requirements, the coupling concerns might outweigh the benefits. The choice is yours based on your project's specific needs and priorities.
MIT
This library is designed to be simple, performant, and easy to use. Contributions are welcome!