Repository navigation
Home
Register services with attributes. Skip manual registration in Program.cs!
Attributes for registration:
[RegisterTransient]
[RegisterScoped]
[RegisterSingleton]Register all attributed services:
serviceCollection.AddByAttribute();
serviceCollection.AddByAttribute(assembly); // Only from specific assembly[RegisterTransient]
public class ExampleService { }
// Equivalent: serviceCollection.AddTransient<ExampleService>();If your class implements an interface with a matching name, it will be registered as that interface:
[RegisterTransient]
public class ExampleService : IExampleService { }
// Equivalent: serviceCollection.AddTransient<IExampleService, ExampleService>();Note: Explicit service types in the attribute override this behavior.
[RegisterTransient<IAnotherExampleService>]
public class ExampleService : ExampleServiceBase, IExampleService, IAnotherExampleService { }
// Equivalent: serviceCollection.AddTransient<IAnotherExampleService, ExampleService>();Register with multiple service types:
[RegisterTransient<ExampleServiceBase, IExampleService, IAnotherExampleService>]
public class ExampleService : ExampleServiceBase, IExampleService, IAnotherExampleService { }
// Equivalent:
// serviceCollection.AddTransient<ExampleServiceBase, ExampleService>();
// serviceCollection.AddTransient<IExampleService, ExampleService>();
// serviceCollection.AddTransient<IAnotherExampleService, ExampleService>();Or use multiple attributes:
[RegisterTransient<ExampleServiceBase>]
[RegisterTransient<IExampleService>]
[RegisterTransient<IAnotherExampleService>]
public class ExampleService : ExampleServiceBase, IExampleService, IAnotherExampleService { }
// Equivalent: One registration per attributeC# < 11: Use type arguments instead of generics:
[RegisterTransient(typeof(IExampleService), typeof(IAnotherExampleService))]
public class ExampleService : ExampleServiceBase, IExampleService, IAnotherExampleService { }For each attribute, only one object is constructed for singleton or scoped services:
[RegisterSingleton<IExampleService, IAnotherExampleService>]
public class ExampleService : IExampleService, IAnotherExampleService { }
// Equivalent:
// serviceCollection.AddSingleton<IExampleService, ExampleService>();
// serviceCollection.AddSingleton(sp => (IAnotherExampleService)sp.GetRequiredService<IExampleService>());Both interfaces resolve to the same instance.
Multiple attributes = different instances:
[RegisterSingleton<IExampleService>]
[RegisterSingleton<IAnotherExampleService>]
public class ExampleService : IExampleService, IAnotherExampleService { }
// Equivalent: Separate singleton for each service typeTo register a hosted service, use:
[RegisterSingleton<IHostedService>]
public class MyWorker : IHostedService { }
// Equivalent: services.AddHostedService<MyWorker>()Tags allow conditional registration. Tags must be constants (string, enum, number):
serviceCollection.AddByAttribute("Example");
serviceCollection.AddByAttribute(14);
serviceCollection.AddByAttribute(ExampleEnum.ExampleValue);Set tags via the attribute:
[RegisterTransient(Tag = "Example")]
public class ExampleService { }
// Only registered if tag matchesCall AddByAttribute for each tag:
serviceCollection.AddByAttribute(); // Untagged
serviceCollection.AddByAttribute(ExampleEnum.ExampleValue);
serviceCollection.AddByAttribute(14);Read more: .NET 8 Release Notes
Register a keyed service:
[RegisterTransient(Key = "Example")]
public class ExampleService { }
// Equivalent: serviceCollection.AddKeyedTransient<ExampleService>("Example");Register a generic class as an unbound generic:
[RegisterTransient]
public class ExampleService<T> { }
// Equivalent: serviceCollection.AddTransient(typeof(ExampleService<>));Explicit interface registration for unbound generics:
[RegisterTransient(typeof(IExampleService<>))]
public class ExampleService<T> : IExampleService<T> { }
// Equivalent: serviceCollection.AddTransient(typeof(IExampleService<>), typeof(ExampleService<>));Note: Use typeof() for unbound generics. No analyzer support (runtime errors only).