Immediate.Injections
1.2.0
dotnet add package Immediate.Injections --version 1.2.0
NuGet\Install-Package Immediate.Injections -Version 1.2.0
<PackageReference Include="Immediate.Injections" Version="1.2.0" />
<PackageVersion Include="Immediate.Injections" Version="1.2.0" />
<PackageReference Include="Immediate.Injections" />
paket add Immediate.Injections --version 1.2.0
#r "nuget: Immediate.Injections, 1.2.0"
#:package Immediate.Injections@1.2.0
#addin nuget:?package=Immediate.Injections&version=1.2.0
#tool nuget:?package=Immediate.Injections&version=1.2.0
Immediate.Injections
Immediate.Injections is a support package for Microsoft.Extensions.DependencyInjection which allows declaring
registrations through attributes. This package supports multiple registration strategies, duplicate-handling strategies,
tagging, and much more.
Installation
dotnet add package Immediate.Injections
Basic Usage
Declaring a registration
Apply one of the three lifetime attributes to a class or record:
[RegisterSingleton]
public class MyService;
[RegisterScoped]
public class MyScopedService;
[RegisterTransient]
public class MyTransientService<T>;
By default (when no RegistrationStrategy is set at the attribute or assembly level), a class is registered as itself.
Generic classes will be registered using open-generics.
Adding declared registrations to the IServiceCollection collection
In your Program.cs, add a call to services.AddXxxServices(), where Xxx is the application identifier. By default,
this is the short form of the assembly name. For example:
- For a project named
Web, it will beservices.AddWebServices() - For a project named
Application.Web, it will beservices.AddApplicationWebServices()
However, this name can be overridden using [assembly: ImmediateAssemblyIdentifierAttribute("SomeIdentifier")].
Tags
Tags can be passed to selectively register only tagged services:
[RegisterSingleton(Tags = ["tag-a"])]
public class MyService;
builder.Services.AddMyProjectServices("tag-a", "tag-b");
Attribute Reference
All three lifetime attributes — RegisterSingleton, RegisterScoped, RegisterTransient — share the same properties.
ServiceType
Registers the class as the specified service type. The class must be assignable to it.
[RegisterSingleton(ServiceType = typeof(IMyService))]
public class MyService : IMyService { }
Alternatively, a concrete registration may be declared using generic attributes.
[RegisterSingleton<IMyService>]
public class MyService : IMyService { }
[RegisterScoped<IService<string>>]
public class MyService<T> : IMyService<string>
RegistrationStrategy
Controls which service types are generated. Mutually exclusive with ServiceType.
| Value | Effect |
|---|---|
None (default) |
Registers as ServiceType if provided, otherwise as the class itself |
Self |
Registers as the concrete class |
ImplementedInterfaces |
Registers as each interface the class implements |
SelfAndImplementedInterfaces |
Registers as the concrete class and each interface |
[RegisterSingleton(RegistrationStrategy = RegistrationStrategy.ImplementedInterfaces)]
public class MyService : IMyService { }
DuplicateStrategy
Controls what happens when a registration for the same service type already exists.
| Value | Generated call |
|---|---|
Append (default) |
services.Add(...) |
Skip |
services.TryAdd(...) |
Replace |
services.Replace(...) |
ServiceKey
Registers the service as a keyed service.
[RegisterSingleton(ServiceKey = "my-key")]
public class MyService { }
Factory
Name of a static factory method on the class to use as ImplementationFactory. The method must be static, return the
class type, and accept (IServiceProvider) for non-keyed or (IServiceProvider, object) for keyed registrations.
Cannot be combined with UseProxyFactory or used on open generic types. Factories cannot be used with generic target
classes.
[RegisterSingleton(Factory = nameof(Create))]
public class MyService
{
public static MyService Create(IServiceProvider sp) => new MyService();
}
UseProxyFactory
When true, the registration uses ServiceProviderServiceExtensions.GetRequiredService<T> (or the keyed equivalent) as
the factory. This produces a proxy registration — it does not register the implementation itself, but resolves it from
the container.
UseProxyFactory = true be combined with the following:
- A provided
Factory, RegistrationStrategy = Self, or- Generic target classes
[RegisterSingleton(ServiceType = typeof(IMyService), UseProxyFactory = true)]
public class MyService : IMyService { }
Tags
Assigns string tags to the registration. When AddXxxServices is called with tag arguments, only registrations that share at least one tag (or registrations with no tags) are included.
[RegisterSingleton(Tags = ["worker", "background"])]
public class BackgroundWorker { }
Global Configuration
ServiceKey and DuplicationStrategy can be configured globally with [RegistrationDefaults] attribute applied to the
assembly.
[assembly: RegistrationDefaults(
RegistrationStrategy = RegistrationStrategy.SelfAndImplementedInterfaces,
DuplicateStrategy = DuplicateStrategy.Replace,
UseProxyFactory = true
)]
Per-attribute values take precedence over assembly defaults.
[RegisterServices]
Apply this attribute to a static void method to have it called as part of AddXxxServices. The method must accept
IServiceCollection as its first parameter, and optionally ReadOnlySpan<string> as its second parameter to receive
the tags passed to AddXxxServices.
public static class ManualRegistrations
{
[RegisterServices]
public static void Register(IServiceCollection services) { ... }
// or, to receive tags:
[RegisterServices]
public static void RegisterWithTags(IServiceCollection services, ReadOnlySpan<string> tags) { ... }
}
[RegisterHostedService]
Apply [RegisterHostedService] to a concrete, non-generic class implementing IHostedService
(or deriving from BackgroundService) to include it in AddXxxServices as a singleton hosted service.
Reference Microsoft.Extensions.Hosting.Abstractions in the consuming project.
[RegisterHostedService(Tags = ["background"])]
public sealed class Worker : BackgroundService
{
protected override Task ExecuteAsync(CancellationToken stoppingToken) => Task.CompletedTask;
}
Like AddHostedService<T>(), this registers IHostedService and ignores repeated registrations
of the same implementation. Tags filters registrations using the usual AddXxxServices tags.
The concrete class is not registered separately.
Set Order to control registration order, for example [RegisterHostedService(Order = 10)].
Services without an explicit order are registered first, followed by ordered services in ascending order.
Omitting the order means that initialization before or after any other hosted service is assumed not to matter.
Explicit orders must be unique across the assembly, including services with different tags (INJ0019).
[RegisterOptions]
Apply this attribute to a class or record to register it as an options type bound to a configuration section, as part of AddXxxServices.
Registering options requires a package reference to Microsoft.Extensions.Options.ConfigurationExtensions.
[RegisterOptions]
public sealed class PositionOptions
{
public string Title { get; set; } = string.Empty;
}
Validation
A validator can be registered alongside the options using the generic attribute. The validator must implement IValidateOptions<TOptions> for the options type.
[Validate]
[RegisterOptions(ValidateOnStart = true)]
public sealed partial class PositionOptions : IValidationTarget<PositionOptions>
{
[NotEmpty]
public string Title { get; set; } = string.Empty;
}
Migration
From Injectio
Immediate.Injections uses a different default registration strategy than Injectio. For a clean migration, set
[assembly: RegistrationDefaults(RegistrationStrategy = RegistrationStrategy.SelfAndImplementedInterfaces, UseProxyFactory = true)]
- The
Tagsparameter receives astring[]instead of a comma-separatedstring. Example:Tags = "foo,bar"becomesTags = ["foo", "bar"] - The
RegistrationStrategy.SelfWithInterfacesenum value changes toRegistrationStrategy.SelfAndImplementedInterfaces - The
Registrationparameter changes toRegistrationStrategy - The
Duplicateparameter becomesDuplicateStrategy - Assembly name override moves from MSBuild property to
[ImmediateAssemblyIdentifier]attribute
From AutoRegisterInject
Immediate.Injections uses a different default registration strategy than Injectio. For a clean migration, set
[assembly: RegistrationDefaults(RegistrationStrategy = RegistrationStrategy.ImplementedInterfaces)].
- The
[TryRegisterXxx]attributes are removed; but the behavior is implemented using a parameter. Example:DuplicateStrategy = DuplicateStrategy.Skip
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. net11.0 is compatible. |
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.15)
- Microsoft.Extensions.Options (>= 10.0.15)
-
net11.0
- No dependencies.
-
net8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Options (>= 8.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.