GenDI.SourceGenerator 2026.6.2.765

dotnet add package GenDI.SourceGenerator --version 2026.6.2.765
                    
NuGet\Install-Package GenDI.SourceGenerator -Version 2026.6.2.765
                    
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="GenDI.SourceGenerator" Version="2026.6.2.765">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="GenDI.SourceGenerator" Version="2026.6.2.765" />
                    
Directory.Packages.props
<PackageReference Include="GenDI.SourceGenerator">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
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 GenDI.SourceGenerator --version 2026.6.2.765
                    
#r "nuget: GenDI.SourceGenerator, 2026.6.2.765"
                    
#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 GenDI.SourceGenerator@2026.6.2.765
                    
#: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=GenDI.SourceGenerator&version=2026.6.2.765
                    
Install as a Cake Addin
#tool nuget:?package=GenDI.SourceGenerator&version=2026.6.2.765
                    
Install as a Cake Tool

GenDI

Generator-based Dependency Injection for .NET — elegant, fast, AOT-ready

CI/CD Pipeline Deploy Documentation NuGet GenDI NuGet GenDI.SourceGenerator NuGet GenDI.Testing NuGet GenDI.Analyzers

Quality Gate Status Bugs Code Smells Coverage Duplicated Lines (%) Lines of Code Reliability Rating Security Rating Technical Debt Maintainability Rating Vulnerabilities

License: MIT Documentation

GenDI is a dependency injection library built on top of C# source generators, providing full compatibility with NativeAOT and trimming. It works as an additional module to Microsoft.Extensions.DependencyInjection, allowing you to register services automatically at compile time — no reflection required.

Say goodbye to constructor bloat

Real-world services accumulate dependencies. With traditional constructor injection this tends to look like this:

// ❌ The "constructor tax" — grows every time a new dependency is added
public class OrderProcessor
{
    private readonly IOrderRepository _orderRepository;
    private readonly IPaymentGateway _paymentGateway;
    private readonly IEmailService _emailService;
    private readonly IInventoryService _inventoryService;
    private readonly ILogger<OrderProcessor> _logger;

    public OrderProcessor(
        IOrderRepository orderRepository,
        IPaymentGateway paymentGateway,
        IEmailService emailService,
        IInventoryService inventoryService,
        ILogger<OrderProcessor> logger)
    {
        _orderRepository = orderRepository;
        _paymentGateway = paymentGateway;
        _emailService = emailService;
        _inventoryService = inventoryService;
        _logger = logger;
    }
}

With GenDI's property injection, the same class becomes clean and self-documenting:

// ✅ Declare what you need — GenDI wires everything at compile time
[Injectable<IOrderProcessor>(ServiceLifetime.Scoped)]
public class OrderProcessor : IOrderProcessor
{
    [Inject] public required IOrderRepository OrderRepository { get; init; }
    [Inject] public required IPaymentGateway PaymentGateway { get; init; }
    [Inject] public required IEmailService EmailService { get; init; }
    [Inject] public required IInventoryService InventoryService { get; init; }
    [Inject] public required ILogger<OrderProcessor> Logger { get; init; }
}

No private fields. No constructor ceremony. No manual wiring. Just declare your dependencies and move on.

Key features and developer benefits

  • Property injection as first-class citizen: use [Inject] on required init-only properties — dependencies read like documentation, not plumbing.
  • Zero boilerplate registration: a single [Injectable] attribute replaces AddScoped<TImpl>() calls scattered across startup files.
  • Readable generated flow: activation is emitted as explicit new + GetRequiredService<T>(), making the wiring transparent and debuggable.
  • Compile-time safety: the C# compiler enforces every required [Inject] property is assigned — you cannot accidentally skip a dependency. Container registration errors (unregistered services) remain runtime exceptions, just like standard DI.
  • Deterministic registration order: Group + Order give you predictable, testable pipeline composition.
  • Attribute-first contract mapping: combine [Injectable], [Injectable<TService>], and [ServiceInjection] with clear intent.
  • Keyed services support: works with both native [FromKeyedServices] and GenDI [Inject(Key = ...)].
  • Factory-first registration: use [InjectableFactory<TService>] on static methods when construction should be centralized.
  • Module filtering: group registrations with [InjectableModule] / Module and load only selected modules.
  • Registration strategy control: RegistrationMultiplicity + RegistrationEmissionStrategy let you choose Single/Multiple and Add/TryAdd generation semantics.
  • Options mapping evolution: [OptionConfig] supports optional key fallback (type name) plus optimized AddOptions<T>().BindConfiguration(section) registration.
  • Testing ergonomics: GenDI.Testing includes a fluent ServiceBuilder for xUnit/unit-test composition.
  • Open-generic safety: open-generic registrations are bypassed and reported as generator warnings (GENDISG001).
  • No runtime scanning cost: compile-time generation eliminates startup overhead from reflection-based scanning.
  • AOT/trimming friendly by design: safe path for teams that need NativeAOT, without forcing this concern for every project.

Installation

dotnet add package GenDI
dotnet add package GenDI.SourceGenerator
dotnet add package GenDI.Testing

GenDI.SourceGenerator now bundles GenDI.Analyzers and ships buildTransitive/GenDI.SourceGenerator.props (Using Include="GenDI").
GenDI remains the runtime package (no buildTransitive content).
When using GenDI.SourceGenerator, you normally should not install GenDI.Analyzers separately to avoid duplicate diagnostics/code-fix hints.


Usage

Using InjectableAttribute

[ServiceInjection]
public interface IMyService
{
    void Execute();
}

[Injectable(ServiceLifetime.Singleton, Group = 10, Order = 1)]
public class MyService : IMyService
{
    public void Execute() => Console.WriteLine("Service injected!");
}

ServiceInjectionAttribute also supports an optional fallback lifetime:

[ServiceInjection(ServiceLifetime.Scoped)]
public interface IScopedContract
{
}

Thread isolation fallback can also be configured at contract level:

[ServiceInjection(ServiceLifetime.Scoped, ThreadIsolation = ThreadIsolationPolicy.Singleton)]
public interface IThreadIsolatedContract
{
}

Fallback precedence is: Injectable > ServiceInjection > Transient.

InjectableAttribute supports:

  • Lifetime (constructor argument, default Transient)
  • Group (optional, default int.MaxValue)
  • Order (optional, default int.MaxValue)
  • ServiceType:
    • [Injectable]null (no explicit contract)
    • [Injectable<TService>]typeof(TService) as explicit contract (additive with [ServiceInjection])
  • Key (optional, default null) for keyed service registration generation
  • ThreadIsolation (optional) using ThreadIsolationPolicy.{Singleton|Scoped|Transient} for thread-local resolution cache
  • Module (optional) to associate registration with a module group

Service registration emission order is:

  1. Group
  2. Order
  3. Service type name (ordinal)

Registering Services

using YourProject.DependencyInjection; // generated by GenDI in the consumer project namespace

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGenDIServices(); // if using decorators, call AddGenDIServices() after all other registrations to ensure correct ordering
var app = builder.Build();
app.Run();

Property Injection with [Inject]

Declare dependencies as required init-only properties and mark them with [Inject]. GenDI generates the activation code — no constructor needed:

[Injectable<IOrderProcessor>(ServiceLifetime.Scoped)]
public class OrderProcessor : IOrderProcessor
{
    [Inject] public required IOrderRepository Repository { get; init; }
    [Inject] public required IPaymentGateway Payment { get; init; }
    [Inject] public required ILogger<OrderProcessor> Logger { get; init; }

    public async Task ProcessAsync(Order order)
    {
        Logger.LogInformation("Processing order {Id}", order.Id);
        await Repository.SaveAsync(order);
        await Payment.ChargeAsync(order);
    }
}

[Inject] also supports optional Key for keyed dependency resolution:

[Inject(Key = "primary")]
public required IMyService Service { get; init; }

[Inject] also supports lifetime override for indirect registration discovery:

[Inject(ServiceLifetime.Scoped)]
public required IMyService Service { get; init; }

Precedence for indirect registration lifetime is: Inject > Injectable > ServiceInjection > Transient (tie-break favors Scoped > Singleton > Transient).

For optional dependencies that should not throw when unregistered, use [InjectOptional]:

[InjectOptional]
public required IMyService? OptionalService { get; init; }

For environment-conditional registration, combine [Injectable] with [ConditionalInjectable]:

[Injectable<IMyService>(ServiceLifetime.Singleton)]
[ConditionalInjectable("Development")]
public sealed class DevOnlyService : IMyService { }

For decorators, mark the wrapper with [DecoratorFor<TService>] or let GenDI infer the [ServiceInjection] contract with non-generic [DecoratorFor(Order = ...)]:

[Injectable<IMyService>(ServiceLifetime.Singleton)]
public sealed class CoreService : IMyService
{
    public void Execute() { }
}

[DecoratorFor<IMyService>(Order = 0)]
public sealed class LoggingDecorator(IMyService inner) : IMyService
{
    public void Execute() => inner.Execute();
}

[DecoratorFor(Order = 1)]
public sealed class ValidationDecorator : IMyService
{
    [Inject]
    public required IMyService Inner { get; init; }

    public void Execute() => Inner.Execute();
}

Decorator pipelines are emitted statically in ascending Order; ties fall back to the decorator type name using ordinal comparison. Decorators must expose a public constructor parameter or [Inject] init-only property matching the decorated service contract.

For factory registration, annotate static factory methods:

[InjectableModule("Billing")]
public static class BillingFactories
{
    [InjectableFactory<IMyService>(ServiceLifetime.Singleton)]
    public static IMyService Create() => new MyService();
}

⚠️ [InjectableFactory<TService>] supports only closed-generic types. Open-generic return types, parameters, generic factory methods, or generic containing types are ignored and emitted as warnings.

To bind options automatically:

[OptionConfig("Features:MyOptions")]
public sealed class MyOptions
{
    public string? Name { get; init; }
}

Constructor injection is also supported and can use the native DI attribute:

public MyConsumer([FromKeyedServices("primary")] IMyService service) { }

Analyzer diagnostics (GenDI.Analyzers)

GenDI.Analyzers currently publishes:

  • GENDI001[Inject] requires init-only property
  • GENDI002[Injectable] requires concrete non-abstract class
  • GENDI003 — constructor injection can be converted to GenDI property injection (code-fix available)
  • GENDI004 — non-generic [DecoratorFor] must resolve exactly one closed [ServiceInjection] contract
  • GENDI005 — decorators must expose the decorated contract as a constructor parameter or [Inject] property

Official diagnostics list:

Service Contract Discovery

  • GenDI discovers services from [ServiceInjection] in implemented interfaces and base types.
  • Injectable<TService> is also added to the generated registration list when provided.
  • If no [ServiceInjection] is found in the inheritance/implementation chain, the concrete class is registered as its own service.

Generated Coverage Configuration

By default, generated extensions are included in coverage (no [ExcludeFromCodeCoverage]). You can control this per assembly:

[assembly: GenDI.GenDICoveration(false)] // add [ExcludeFromCodeCoverage] to generated extension

NativeAOT and Trimming (Phase 3)

GenDI includes linker descriptors and validation projects for trimming and NativeAOT scenarios.

Publish with trimming

dotnet publish tests/GenDI.Phase3.TrimValidation.App/GenDI.Phase3.TrimValidation.App.csproj -c Release

Publish with NativeAOT

dotnet publish tests/GenDI.Phase3.NativeAotValidation.App/GenDI.Phase3.NativeAotValidation.App.csproj -c Release -r linux-x64
<linker>
  <assembly fullname="YourAssemblyName">
    <type fullname="YourAssemblyName.DependencyInjection.GenDIServiceCollectionExtensions" preserve="all" />
  </assembly>
</linker>

Documentation Website (Phase 4)

GenDI now ships an English-first Docusaurus documentation website under website/, with a theme aligned to net-mediate.

Local docs development

cd website
npm ci
npm run start

Production docs build

cd website
npm run build

GitHub Pages deployment is handled by .github/workflows/deploy-docs.yml.

Benchmarks (Phase 4)

GenDI now includes a dedicated BenchmarkDotNet project:

  • tests/GenDI.Benchmarks

Primary benchmark focus is startup registration cost:

  • generated registration (AddGenDIServices)
  • reflection-based runtime scanning

Latest published benchmark report:

  • docs/BENCHMARKS.md

Packaging and CI/CD Baseline (Phase 4 / early Phase 5)

The repository includes:

  • versions.props for centralized dynamic versioning
  • pack.props for package metadata and packing defaults
  • .github/workflows/ci-cd.yml and .github/workflows/auto-publish.yml prepared for Sonar/NuGet flows

Local Tooling and Git Hooks

The repository uses local tools and Husky hooks:

  • dotnet-tools.json includes csharpier and husky
  • pre-commit runs:
    • dotnet csharpier format .
    • dotnet test

For fresh clones, src/GenDI/GenDI.csproj runs a pre-restore target that executes dotnet tool restore and dotnet husky install.


Compatibility

Platform / Framework Status
.NET 8+ YES
NativeAOT YES
Trimming YES
Microsoft.Extensions.DependencyInjection YES
ASP.NET Core Minimal API YES
Worker Service / hosted services YES
Blazor WebAssembly YES
MAUI / mobile AOT Manual validation recipe
F# Exploration only (no generated AddGenDIServices())

Roadmap

Phase Description Status
1 InjectableAttribute - attribute-based registration Implemented
2 Attribute model + contract discovery + ordering Implemented
3 Advanced NativeAOT support (ILLink.xml, trimming, AOT) Implemented
4 Benchmarks, website/docs, and CI hardening Implemented
5 Official NuGet publication Implemented
6 Developer experience and ecosystem expansion In Progress

See the full plan in ROADMAP.md.

Phase 6 delivery baseline (single status source)

The canonical track status is maintained in /home/runner/work/GenDI/GenDI/docs/ROTEIRO_FASE6.md and mirrored here:

Track Status
4.1 Source-generator quality Delivered
4.2 Registration model (RM-01..RM-12) Delivered
4.3 Platform/framework support Delivered
4.4 Testing ergonomics Delivered
4.5 Explicit registration strategies (Add/TryAdd) Delivered
4.6 OptionConfig evolution Delivered
4.7 Tooling/IDE Pending
4.8 Observability Pending
4.9 Community/ecosystem Pending

Detailed references:

Detailed RM-01..RM-12 documentation:

Platform/framework notes:


Contributing

Contributions are welcome! Please read CONTRIBUTING.md before opening a pull request.


License

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

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.0

    • GenDI (>= 2026.6.2.765)

NuGet packages (3)

Showing the top 3 NuGet packages that depend on GenDI.SourceGenerator:

Package Downloads
NetMediate

Mediator alternative for MediatR.

NetMediate.SourceGeneration

Source generator package for NetMediate. Installs the generator directly and wires NetMediate runtime + GenDI.SourceGenerator through buildTransitive.

NetMediate.Quartz

Quartz.NET-backed persistent notification scheduler for NetMediate. Enables crash recovery and cluster-distributed notification execution.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2026.6.2.765 78 6/2/2026
2026.5.25.1004 726 5/25/2026
2026.5.19.1218 529 5/19/2026
2026.5.19.867 101 5/19/2026
2026.5.19.149 96 5/19/2026
2026.5.18.1231 96 5/18/2026
2026.5.18.1180 94 5/18/2026
2026.5.18.894 100 5/18/2026
2026.5.17.848 142 5/17/2026
2026.5.17.753 95 5/17/2026
26.5.17.123 112 5/17/2026
26.5.16.1332 97 5/16/2026
26.5.16.989 158 5/16/2026
26.5.16.968 98 5/16/2026
26.5.16.899 94 5/16/2026
26.5.16.206 160 5/16/2026
26.5.15.1391 118 5/15/2026
26.5.14.661 301 5/14/2026
26.5.13.1053 130 5/13/2026
26.5.12.1224 148 5/12/2026
Loading failed