Skip to content

ServiceRegistrationAttribute

ServiceRegistrationAttribute is a declarative way to mark a class for DI registration without writing an explicit fluent selector. The Indago generator reads the attribute at build time and includes the type in the generated provider; no runtime reflection occurs.

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class ServiceRegistrationAttribute : Attribute

Applied to a class, it instructs the generator to register the class in the DI container. When applied without arguments, the type is registered as itself (AsSelf) with ServiceLifetime.Singleton.

Constructors:

// Register as self, Singleton (default)
ServiceRegistrationAttribute()
// Register against explicit service types, Singleton
ServiceRegistrationAttribute(params Type[] serviceTypes)
// Register against explicit service types with a specified lifetime
ServiceRegistrationAttribute(ServiceLifetime lifetime, params Type[] serviceTypes)

Properties:

PropertyTypeDescription
ServiceTypesImmutableArray<Type>The service types to register against. Empty means register as self.
LifetimeServiceLifetimeThe DI lifetime. Defaults to Singleton.

AllowMultiple = true means a single class can carry multiple [ServiceRegistration] attributes to be registered against different service types or with different lifetimes simultaneously.

The generic variants provide a concise way to specify one to four explicit service types without passing typeof(...) arguments.

[ServiceRegistration<IMyService>]
public class MyService : IMyService { }

Registers MyService as IMyService. Accepts an optional ServiceLifetime constructor argument (defaults to Singleton).

ServiceRegistrationAttribute<TService1, TService2>

Section titled “ServiceRegistrationAttribute<TService1, TService2>”
[ServiceRegistration<IMyService, IAlternate>]
public class MyService : IMyService, IAlternate { }

Registers against two service types.

ServiceRegistrationAttribute<TService1, TService2, TService3>

Section titled “ServiceRegistrationAttribute<TService1, TService2, TService3>”

Registers against three service types.

ServiceRegistrationAttribute<TService1, TService2, TService3, TService4>

Section titled “ServiceRegistrationAttribute<TService1, TService2, TService3, TService4>”

Registers against four service types.

All generic variants accept an optional ServiceLifetime constructor argument:

[ServiceRegistration<IMyService>(ServiceLifetime.Scoped)]
public class MyService : IMyService { }
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public class RegistrationLifetimeAttribute : Attribute

Overrides the DI lifetime for a type independently of [ServiceRegistration]. Useful when you want to set a single lifetime on a base class or interface and have it apply across all registrations of that type.

public RegistrationLifetimeAttribute(ServiceLifetime lifetime)
PropertyTypeDescription
LifetimeServiceLifetimeThe overriding lifetime.
public static IServiceCollection AddIndagoServiceRegistrations(
this IServiceCollection services,
IIndagoProvider provider
)

Extension method on IServiceCollection that uses provider.Scan() to find all classes decorated with any [ServiceRegistration] variant and adds them to the container. The scan itself is resolved at build time; this call at startup simply replays the pre-built registrations.

Usage:

// In Program.cs / Startup.cs
services.AddIndagoServiceRegistrations(IndagoProvider.Instance);
// Scoped service registered as IMyService — lifetime from [ServiceRegistration] itself
[ServiceRegistration<IMyService>(ServiceLifetime.Scoped)]
public class MyService : IMyService { }
// Class carrying a separate lifetime override via [RegistrationLifetime]
[ServiceRegistration]
[RegistrationLifetime(ServiceLifetime.Scoped)]
public class AnotherService : IAnotherService { }
// Multiple registrations on one class
[ServiceRegistration<IMyService>]
[ServiceRegistration<IAlternate>(ServiceLifetime.Transient)]
public class DualService : IMyService, IAlternate { }
// Wire up everything in one call
builder.Services.AddIndagoServiceRegistrations(IndagoProvider.Instance);
  • Registration is a compile-time operation. The generator discovers [ServiceRegistration]-decorated types during the build, not at application startup.
  • Abstract classes and static classes are implicitly excluded — AddClasses() skips them by default.
  • If ServiceTypes is empty (i.e. the attribute is applied with no type arguments), the class is registered as its own concrete type (AsSelf).