Quickstart
Quickstart
Section titled “Quickstart”This page assumes you have already installed Indago.
1. Obtain the Provider
Section titled “1. Obtain the Provider”The generator emits an IndagoProvider class into your assembly and exposes it through the static IndagoProvider.Instance property:
IIndagoProvider provider = IndagoProvider.Instance;IndagoProvider is internal, so Instance is available throughout your project. You can hold it in a variable or field, or call it inline — IIndagoProvider is a plain interface you can also inject.
2. Scan for Types
Section titled “2. Scan for Types”Call GetTypes() with a fluent selector. The selector is a lambda whose text the generator captures at build time via [CallerArgumentExpression]:
IEnumerable<Type> types = provider.GetTypes(s => s.FromAssemblyOf<Program>() .AddClasses() .AsImplementedInterfaces());The full selector fluent API is covered in the Reference section. Common starting points:
| Selector step | What it does |
|---|---|
FromAssemblyOf<T>() | Scope the scan to the assembly containing T |
FromAssemblies() | Include all loaded assemblies |
FromAssemblyDependenciesOf<T>() | Include assemblies referenced by T’s assembly |
AddClasses() | Filter to concrete (non-abstract) classes |
GetTypes() | Return all matched types without further filtering |
3. Register with Dependency Injection
Section titled “3. Register with Dependency Injection”Option A — Scan() directly into IServiceCollection
Section titled “Option A — Scan() directly into IServiceCollection”IIndagoProvider.Scan() combines the scan and registration in one call:
var builder = WebApplication.CreateBuilder(args);var provider = IndagoProvider.Instance;
provider.Scan(builder.Services, s => s.FromAssemblyOf<Program>() .AddClasses() .AsImplementedInterfaces() .WithSingletonLifetime());Option B — AddIndagoServiceRegistrations()
Section titled “Option B — AddIndagoServiceRegistrations()”AddIndagoServiceRegistrations is an IServiceCollection extension method that reads [ServiceRegistration] attributes applied directly to classes and registers them according to their declared lifetime (default: Singleton):
// On your service class:[ServiceRegistration<IMyService>]public class MyService : IMyService { }
// In Program.cs:builder.Services.AddIndagoServiceRegistrations(provider);The signature is:
public static IServiceCollection AddIndagoServiceRegistrations( this IServiceCollection services, IIndagoProvider provider);4. What the Generated Code Looks Like
Section titled “4. What the Generated Code Looks Like”Conceptually, the generator emits something like this (simplified):
// IndagoProvider.g.cs — auto-generated, do not editinternal sealed class IndagoProvider : IIndagoProvider{ public IEnumerable<Type> GetTypes( Func<IReflectionTypeSelector, IEnumerable<Type>> selector, int lineNumber = 0, string filePath = "", string argumentExpression = "") { // Hash of "s => s.FromAssemblyOf<Program>().AddClasses().AsImplementedInterfaces()" return argumentExpression switch { "abc123==" => new[] { typeof(MyService), typeof(OtherService) }, // ... other call sites _ => Enumerable.Empty<Type>() }; } // ...}There are no calls to Assembly.GetTypes(), no reflection, and no dictionary lookups over runtime metadata. Every result is a compile-time constant array.
5. Verifying the Registration
Section titled “5. Verifying the Registration”Add a quick sanity check after Build():
var app = builder.Build();var svc = app.Services.GetRequiredService<IMyService>(); // throws if not registeredNext Steps
Section titled “Next Steps”- AOT Publishing — publish with Native AOT and zero trim warnings
- Reference section — full selector API documentation