Sample Applications
Sample Applications
Section titled “Sample Applications”The samples/ tree is a set of
worked examples that exercise Indago end-to-end. Three reusable libraries declare services in
different registration styles; hosts consume all three and assert — in process — that Indago
discovered exactly the expected service set, then publish under a zero-warning Native AOT guardrail.
You can read the selector expressions below to understand how scanning resolves without running anything — that is the whole point of a compile-time provider.
The three libraries
Section titled “The three libraries”Each library is a plain class library that references Indago. Collectively they cover
interface-matching and attribute-based registration, three lifetimes, and one opt-out type.
| Library | Style | Lifetime(s) | Notable |
|---|---|---|---|
Indago.Samples.Catalog | interface-matching | Singleton | IXxxService → XxxService |
Indago.Samples.Notifications | attribute ([ServiceRegistration]) | Transient (AsSelf) | generic + non-generic attribute |
Indago.Samples.Diagnostics | interface-matching | Scoped | one [ExcludeFromSampleScan] opt-out |
How a host scans them
Section titled “How a host scans them”A host calls provider.Scan(services, selector) once per library. Each selector is hashed at the
call site and resolved by the source generator at build time into concrete registrations — there is
no runtime reflection.
1. Interface-matching, Singleton (Catalog)
Section titled “1. Interface-matching, Singleton (Catalog)”provider.Scan( services, z => z.FromAssemblyOf<IProductService>() .AddClasses(f => f.InExactNamespaceOf<IProductService>()) .AsMatchingInterface() .WithSingletonLifetime());AsMatchingInterface() registers ProductService as IProductService, CategoryService as
ICategoryService, and so on.
2. Attribute-based, Transient as-self (Notifications)
Section titled “2. Attribute-based, Transient as-self (Notifications)”provider.Scan( services, z => z.FromAssemblyOf<NotificationDispatcher>() .AddClasses(f => f.WithAttribute<ServiceRegistrationAttribute>()) .AsSelf() .WithTransientLifetime());Only types carrying [ServiceRegistration] are registered, each as its own concrete type.
3. Interface-matching with an opt-out, Scoped (Diagnostics)
Section titled “3. Interface-matching with an opt-out, Scoped (Diagnostics)”provider.Scan( services, z => z.FromAssemblyOf<IHealthCheck>() .AddClasses(f => f.WithoutAttribute<ExcludeFromSampleScanAttribute>()) .AsMatchingInterface() .WithScopedLifetime());WithoutAttribute<ExcludeFromSampleScanAttribute>() is why the opt-out type never appears in the
discovered set — the host asserts its absence.
The hosts
Section titled “The hosts”| Host | Kind | Proves |
|---|---|---|
Indago.Samples.Console | console | discovery via IndagoProvider.Instance; exits non-zero on mismatch |
Indago.Samples.Web | ASP.NET minimal API | fail-fast at startup on mismatch; /services endpoint lists discovery |
Both hosts hold a hard-coded expected service set and compare it to what Indago discovered, failing the process (and therefore the CI smoke test) on any mismatch. Both are published under the zero-warning Native AOT policy as discrete, named pipeline steps.