Simplifying Dependency Injection with Campsis.AutoInject
Dependency Injection (DI) is a cornerstone of modern .NET applications, ensuring loose coupling, testability, and maintainability. However, traditional DI configurations can quickly become verbose and boilerplate-heavy. Developers often find themselves manually registering every service, leading to cluttered Program.cs
files and a tedious onboarding experience.
Enter Campsis.AutoInject — a lightweight yet powerful automatic DI registration library that eliminates boilerplate code, making .NET DI effortless and intuitive. This article explores the why, how, and real-world benefits of using Campsis.AutoInject in your next project.
The Problem with Manual DI
Imagine a standard .NET application with multiple services:
services.AddScoped<IUserService, UserService>();
services.AddSingleton<ICacheService, MemoryCacheService>();
services.AddTransient<ILogger, Logger>();
For every new service, you must:
- Remember to register it in
Program.cs
. - Choose the correct lifecycle (
Scoped
,Singleton
,Transient
). - Handle service variations (e.g., multiple implementations).
This process is not only redundant but also error-prone — if you forget to register a service, runtime errors will follow.
The Campsis.AutoInject Solution
Campsis.AutoInject automates service registration by scanning assemblies for annotated classes and registering them accordingly.
How It Works
Simply annotate your services with SingletonAttribute
, ScopedAttribute
, or TransientAttribute
:
[Singleton(typeof(IUserService))]
public class UserService : IUserService { }
[Scoped(typeof(ICacheService))]
public class MemoryCacheService : ICacheService { }
[Transient(typeof(ILogger))]
public class Logger : ILogger { }
Then, in Program.cs
, just call one method:
builder.Services.UseAutoInjection();
That’s it! Campsis.AutoInject scans your assembly, finds the annotated services, and registers them automatically.
Keyed Injection
Campsis.AutoInject supports keyed dependencies, allowing multiple implementations of the same interface.
Example: Injecting Multiple Storage Implementations
[Singleton(typeof(IStorageBroker), WithKey : "SQL")]
public class SqlStorageBroker : IStorageBroker { }
[Singleton(typeof(IStorageBroker), WithKey : "MONGO")]
public class MongoStorageBroker : IStorageBroker { }
Then inject the appropriate implementation using FromKeyedServices
:
[Singleton(typeof(IStudentService))]
public class StudentService(
[FromKeyedServices("SQL")] IStorageBroker sqlStorageBroker,
[FromKeyedServices("MONGO")] IStorageBroker mongoStorageBroker) : IStudentService
{
public ValueTask<string> InsertStudentIntoMongoAsync(string student) =>
mongoStorageBroker.InsertStudentAsync(student);
public ValueTask<string> InsertStudentIntoSQLAsync(string student) =>
sqlStorageBroker.InsertStudentAsync(student);
}
This allows seamless switching between different implementations at runtime.
Why Choose Campsis.AutoInject?
- Eliminates repetitive DI code
- Prevents forgotten registrations
- Encourages clean architecture
- Works seamlessly in Blazor, ASP.NET Core, and console apps.
Try it today
Install the library and try it! waiting your feedback :)
dotnet add package Campsis.AutoInject
Happy coding!