Skip to content

Quickstart

This page assumes you have already installed Indago.

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.

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 stepWhat 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

Option A — Scan() directly into IServiceCollection

Section titled “Option A — Scan() directly into IServiceCollection”

IIndagoProvider.Scan() combines the scan and registration in one call:

Program.cs
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);

Conceptually, the generator emits something like this (simplified):

// IndagoProvider.g.cs — auto-generated, do not edit
internal 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.

Add a quick sanity check after Build():

var app = builder.Build();
var svc = app.Services.GetRequiredService<IMyService>(); // throws if not registered
  • AOT Publishing — publish with Native AOT and zero trim warnings
  • Reference section — full selector API documentation