Manual registration
services.AddScoped<IOrderService, OrderService>();
Precise, but repetitive. The more services you add, the more startup code becomes a maintenance list.
Attribute-free compile-time DI for .NET
Injectlynx reads a strongly typed C# convention DSL during build and emits plain
IServiceCollection registrations. Your services stay clean, startup stays predictable,
and dependency mistakes fail before they reach production.
The problem
Every .NET team starts with a few obvious registrations. Then the application grows: services, handlers, clients, decorators, keyed implementations, feature libraries, hosted workers, and Native AOT constraints all pull the startup file in different directions.
Manual registration is explicit, but repetitive and easy to forget. Runtime scanning is convenient, but it moves important decisions into reflection paths that are harder to validate, trim, and reason about. Injectlynx gives developers a third path: explicit conventions checked at compile time.
services.AddScoped<IOrderService, OrderService>();
Precise, but repetitive. The more services you add, the more startup code becomes a maintenance list.
services.Scan(...);
Convenient, but reflection-driven. It can hide registration decisions until runtime and complicate trimming.
builder.Services.AddInjectlynxServices();
Convention-based, generated at build time, and emitted as normal Microsoft DI code.
Why it is important
Injectlynx turns service registration from a runtime discovery concern into generated source your IDE, build, CI, and Native AOT pipeline can understand.
Service classes do not need Injectlynx attributes or framework-specific markers. Your domain and application types stay portable.
Missing matching interfaces, duplicate registrations, invalid DSL declarations, dependency cycles, and lifetime issues can surface during build.
The generator emits direct AddScoped, AddSingleton, and AddTransient registrations for IServiceCollection.
No runtime assembly scanning means a cleaner path for trimming-sensitive apps and Native AOT validation.
How developers use it
The primary package brings the DSL and the Roslyn source generator into your app.
Use normal C# syntax with IntelliSense: namespaces, name filters, interfaces, lifetimes, exclusions, decorators, and keys.
At startup, call AddInjectlynxServices() or your custom generated extension method.
using Injectlynx;
namespace Shop.Application;
public static class ApplicationServiceConventions
{
public static void Configure(IServiceConventionBuilder services)
{
services
.FromNamespace("Shop.Application.Services")
.WhereNameEndsWith("Service")
.AsMatchingInterface()
.WithScopedLifetime();
}
}
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddInjectlynxServices();
var app = builder.Build();
app.Run();
// Emitted during build.
services.AddScoped<IOrderService, OrderService>();
services.AddScoped<ICustomerService, CustomerService>();
services.AddScoped<IInvoiceService, InvoiceService>();
How development gets faster
Create OrderService : IOrderService in the selected namespace and the convention picks it up at build time.
The DSL is C#, so type-based registrations work with rename refactoring and IDE navigation.
Enable the development report to see entries like OrderService -> IOrderService (Scoped).
Application, infrastructure, and feature libraries can each publish a generated registration method with its own namespace.
What it solves
It solves service registration drift: the gap between the classes your team writes and the DI graph your application actually starts with. Instead of trusting humans to keep a long startup list synchronized, or trusting runtime scanning to discover the right shape, Injectlynx captures your team’s rules once and regenerates deterministic registration code as the codebase changes.
Start now
Injectlynx targets netstandard2.0, net8.0, net9.0, and net10.0.
The generator ships inside the primary package, so most applications install one dependency.
dotnet add package Injectlynx
dotnet build -p:InjectlynxDevelopmentReport=true