SourceGen.Ioc Overview
SourceGen.Ioc is a C# source generator that extends Microsoft.Extensions.DependencyInjection.Abstractions (MS.E.DI.A) — it is not a replacement for Microsoft.Extensions.DependencyInjection (MS.E.DI).
Its primary goal is to generate IServiceCollection registration code at compile time, eliminating repetitive manual registration while keeping your business code free of DI framework concerns. An optional compile-time container ([IocContainer]) is available for high-performance or specialized scenarios (such as building a tag-filtered container for a specific subsystem).
Quick Start
Install the package:
dotnet add package SourceGen.IocThe simplest way to get started is to register services without modifying their source code:
// In a dedicated registration file — your service types stay attribute-free
[assembly: IocRegisterFor<UserService>(ServiceLifetime.Scoped, ServiceTypes = [typeof(IUserService)])]
[assembly: IocRegisterFor<OrderService>(ServiceLifetime.Scoped, ServiceTypes = [typeof(IOrderService)])]// In Program.cs
var services = new ServiceCollection();
services.AddMyProject(); // Generated extension methodTIP
Use [IocRegisterFor] and [IocRegisterDefaults] in dedicated registration files to keep your domain types completely free of SourceGen.Ioc attributes. Use [IocRegister] directly on infrastructure types when local annotation improves readability.
Why Use SourceGen.Ioc?
Reduce Boilerplate
- Centralized Defaults —
[IocRegisterDefaults]lets you define lifetime, decorators, and tags once for all implementations of a service type - no repetitive per-class configuration. - Batch Registration —
ImplementationTypeson defaults registers multiple types without individual attributes. - CLI Tool —
SourceGen.Ioc.Clican add attributes or generate registration files for existing codebases in bulk.
Native AOT Compatible
- All generated code compiles to Native AOT without trimming warnings or runtime reflection.
- The optional
[IocContainer]generates fully typed resolution code — noActivator.CreateInstanceor expression tree compilation at runtime.
Compile-Time Safety
- Lifecycle Analysis — Detects risky lifetime chains (for example, singleton → scoped/transient).
- Circular Dependency Detection — Reports circular constructor dependencies at compile time.
- Decorator Constraint Validation — Skips invalid decorators when generic constraints are not satisfied.
| ID | Severity | Description |
|---|---|---|
| SGIOC002 | Error | Circular dependency detected among registered services. |
| SGIOC003 | Error | Singleton service depends on a scoped service. |
| SGIOC004 | Error | Singleton service depends on a transient service (directly or through Lazy<T>; a Func factory creates a new instance per call and is not reported). |
| SGIOC005 | Error | Scoped service depends on a transient service (directly or through Lazy<T>; a Func factory creates a new instance per call and is not reported). |
Better Generic Support
- Open Generic Auto-Discovery — Automatically discovers closed generic services from constructor/property/field/method injection and
IServiceProviderinvocations. - Nested Generic Support — Supports nested open generic patterns (for example,
IHandler<Request<T>, List<T>>) thatMS.E.DIcannot resolve at runtime.
Flexible Configuration
- Keys — Register and resolve keyed services with value keys or C# expression keys.
- Tags — Group registrations behind runtime tag filters for startup-time profile selection.
- Decorators — Build ordered decorator chains with generic constraint checking.
- Property/Field/Method Injection — Supports
[IocInject](and[Inject]-named attributes) for member and parameter injection. - Factory & Instance — Use static factory methods or static instances for custom creation logic.
- Generated Container — Use
[IocContainer]to generate a high-performance compile-time container for specific scenarios.
Core Concepts
Attributes Reference
| Attribute | Purpose |
|---|---|
[IocRegisterFor] / [IocRegisterFor<T>] | Register types you do not own, or any type — without modifying its source code. |
[IocRegisterDefaults] / [IocRegisterDefaults<T>] | Define shared policy (lifetime, decorators, tags) for all implementations of a service type. |
[IocImportModule] / [IocImportModule<T>] | Import defaults from another module type or assembly, and the services of another container (module). |
[IocRegister] / [IocRegister<T>] | Register a class directly on its declaration (best for infrastructure code you own). |
[IocInject] | Mark constructor/property/field/method/parameter for generator-aware injection behavior. |
[IocDiscover] / [IocDiscover<T>] | Manually discover closed generic types for open-generic registration. |
[IocGenericFactory] | Map discovered closed generic types to generic factory method type parameters. |
[IocContainer] | Generate a compile-time container on a partial class (advanced). |
NOTE
Generic attributes ([Attribute<T>]) require C# 11 or later.
Generated Outputs
SourceGen.Ioc generates two kinds of output:
- Registration extension method (
Add{ProjectName}) — the primary output, always generated. - Container implementation (
[IocContainer]) — optional, for high-performance or tag-filtered container scenarios.
// Generated registration extension — use with any MS.E.DI-compatible container
public static IServiceCollection AddMyProject(this IServiceCollection services, params IEnumerable<string> tags)
{
// registration code...
return services;
}IMPORTANT
The generated container does not replace MS.E.DI. It does not parse IServiceCollection registrations — so extension methods such as services.AddLogging() or services.AddOptions() are not available in container-only mode. For general-purpose applications, use MS.E.DI as the primary container and SourceGen.Ioc's generated registration methods as an extension layer. Use [IocContainer] when you need a typed, high-performance container for specific subsystems (for example, a MediatorContainer with IncludeTags = ["Mediator"]).
Diagnostics
SourceGen.Ioc analyzers report SGIOC-prefixed diagnostics in the IDE and at build time. See the Diagnostics Quick Fix Map for the full list.
- Usage validation — attribute misuse, incompatible settings, invalid injection members.
- Design validation — cycles, lifetime issues, duplicate registrations/defaults.
- Keyed/factory validation — key type mismatches, generic factory mapping issues.
- Container validation — unresolved dependencies and container option conflicts.
- Async initialization validation — async inject methods and the
Task<T>accessors and dependencies they require.
Table of Contents
| Document | Description |
|---|---|
| Overview | Entry point, quick start, and feature map. |
| Basic Usage | Registration patterns, external types, and method naming. |
| Default Settings | Shared defaults, implementation lists, module import, and precedence. |
| Injection | Property, field, method, and constructor injection behavior. |
| Keyed Services | Keyed registration and keyed injection patterns. |
| Decorators | Decorator registration and type-constraint behavior. |
| Tags | Tag-based registration and mutually exclusive tag model. |
| Factory & Instance | Static factory methods, static instances, and generic factory mapping. |
| Open Generics | Open generic registration, auto-discovery, and manual discover. |
| Wrapper Types | Lazy, Func, collections, and dictionary resolution. |
| CLI Tool | CLI workflows for attribute and registration file generation. |
| Container | Compile-time container generation and options (advanced). |
| MSBuild Configuration | MSBuild properties controlling generation behavior. |
| Best Practices | Production-safe patterns, decision matrix, and diagnostics quick-fix guide. |