Skip to content

devKennies26/auto-DI-by-attributes

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

30 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

AttributeAutoDI

🌟 Attribute-based automatic dependency injection library for .NET


README-KR

README-KR

Nuget

NUGET

dotnet add package AttributeAutoDI --version 1.0.1


Sample

Sample


πŸ’‘ Motivation

The default DI container in ASP.NET Core is simple and powerful, but having to call builder.Services.AddXXX<>() repeatedly introduces a few pain points:

❌ The more services you implement, the longer and harder your Program.cs becomes to manage

❌ Handling multiple implementations of the same interface requires verbose, error-prone registration

❌ Service intent is not self-explanatory – registration and class definition are separated

πŸ‘‰ What if... classes could declare how they want to be injected? AttributeAutoDI was born from this idea.

It is built on the following principles: βœ… Services should declare their own lifecycle and purpose

βœ… Multiple implementations should be clearly handled via [Primary] or [Named]

βœ… We should reduce boilerplate code in Program.cs without sacrificing readability

Our goal is to simplify Program.cs and Startup.cs as much as possible so you can trust the system to "just work."


🧾 Requirements

  • .NET 6.0 or later
  • Compatible with Microsoft.Extensions.DependencyInjection (ASP.NET Core, Console apps, etc.)

πŸ”₯ Features

βœ… Automatic registration via [Singleton], [Scoped], and [Transient]

⭐ [Primary] support for selecting default implementation

🏷️ [Named] support for explicit injection via constructor parameters

πŸ› οΈ [Options("Section")] for automatic configuration binding

πŸ‘Ύ Executes configuration methods marked with [Execute] inside classes decorated with [PreConfiguration] or [PostConfiguration].


πŸš€ Usage

1. Register the extension

builder.Services.AddAttributeDependencyInjection(builder.Configuration);

or

builder.Services.AddAttributeDependencyInjection(builder.Configuration,typeof(Program).Assembly);

Internally, it expands to:

public static class AttributeInjectionExtension
{
    public static void AddAttributeDependencyInjection(
    this IServiceCollection services,
    IConfiguration configuration,
    Assembly? assembly = null
)
{
    assembly ??= Assembly.GetEntryAssembly();

    services.UsePreConfiguration(assembly!);

    services.UseOptionsBindingInjection(configuration, assembly!);
    services.UseAttributeInjection(assembly!);
    services.UsePrimaryInjection();
    services.UseNameParameterInjection(assembly!);
    services.Replace(ServiceDescriptor.Transient<IControllerActivator, NamedControllerActivator>());

    services.UsePostConfiguration(assembly!);
}

Execution Flow

  1. Execute methods under [PreConfiguration] classes

  2. Register [Options] bindings

  3. Register class dependencies marked with [Singleton], [Transient], or [Scoped]

  4. Register [Primary] dependencies

  5. Register constructor parameter classes and controller activators with [Named]

  6. Execute methods under [PostConfiguration] classes

⚠️ Important: Register in correct order!

βœ”οΈ This works as expected:

builder.Service.AddSingleton...
builder.Service.AddAttributeDependencyInjection 

❌ This may not work correctly:

builder.Service.AddAttributeDependencyInjection
builder.Service.AddSingleton...

If you use both manual and attribute-based registration, always call AddAttributeDependencyInjection() after manual registrations.

2. Attribute-based Auto registration - [Singleton], [Transient], [Scoped]

[Singleton]
public class MyService : IMyService
{
    public string Get() => "hello";
}

This is equivalent to:

builder.Services.AddSingleton<IMyService, MyService>();

3. Primary service selection - [Primary]

[Singleton]
public class MyService : IMyService
{
    public string Get() => "hello";
}

[Primary]
[Singleton]
public class MyPrimaryService : IMyService
{
    public string Get() => "I am primary";
}

When injecting IMyService, the system will prefer MyPrimaryService.

4. Named injection - [Named]

[Singleton]
public class MyService : IMyService
{
    public string Get() => "hello";
}

This will register myService (default camel-case name). Or set custom name:

[Singleton("myNamedService")]
public class MyService : IMyService
{
    public string Get() => "hello";
}

Then inject with:

[Singleton]
public class TestFacade([Named("myNamedService")]IMyservice myservice)
{
...
}
// myservice == MyService

Named injection works in registered Class

5. Options binding via attribute - [Options]

[Options("Sample:Sample")]
public class SampleOption
{
    public string Sample { get; set; } = "";
}

This is equivalent to:

builder.Services.Configure<SampleOption>(configuration.GetSection("Sample:Sample"));

Then you can inject it with:

public class SampleController(
    IOptions<SampleOption> sampleOption) ...

6. Configuration Execution - [PreConfiguration], [PostConfiguration], [Execute]

You can run setup methods before or after AddAttributeDependencyInjection using [Execute] methods.

The execution order is:

PreConfiguration β†’ AddAttributeDependencyInjection β†’ PostConfiguration

[PreConfiguration] //or [PostConfiguration]
public static class Configuration{
    [Execute]
    public static void TestConfig1(IServiceCollection service){
        ...
    }

    [Execute]
    public static void TestConfig2(this IServiceCollection service){
    ...
    }
    
    [Execute]
    public static void TestConfig3(IServiceCollection service, IConfiguration configuration){
        ...
    }

    [Execute]
    public static void TestConfig4(this IServiceCollection service, IConfiguration configuration){
    ...
    }
}

βœ… Only these four method signatures are supported.

ℹ️ Return types are ignored β€” any return type is allowed but not used.


πŸ§ͺ Examples

Check out the AttributeAutoDI.Sample project for practical examples.


πŸ™Œ Contributing

Found a bug? Have an improvement idea? Feel free to open an issue or submit a pull request.


πŸ“„ License

MIT License Copyright (c) 2025

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 99.1%
  • Other 0.9%