RzR.Extensions.UniqueServiceCollection
3.0.0.8109
dotnet add package RzR.Extensions.UniqueServiceCollection --version 3.0.0.8109
NuGet\Install-Package RzR.Extensions.UniqueServiceCollection -Version 3.0.0.8109
<PackageReference Include="RzR.Extensions.UniqueServiceCollection" Version="3.0.0.8109" />
<PackageVersion Include="RzR.Extensions.UniqueServiceCollection" Version="3.0.0.8109" />
<PackageReference Include="RzR.Extensions.UniqueServiceCollection" />
paket add RzR.Extensions.UniqueServiceCollection --version 3.0.0.8109
#r "nuget: RzR.Extensions.UniqueServiceCollection, 3.0.0.8109"
#:package RzR.Extensions.UniqueServiceCollection@3.0.0.8109
#addin nuget:?package=RzR.Extensions.UniqueServiceCollection&version=3.0.0.8109
#tool nuget:?package=RzR.Extensions.UniqueServiceCollection&version=3.0.0.8109
Extends IServiceCollection with methods to register services without creating duplicates and to detect or clean up accidental duplicate registrations.
The problem this solves: in solutions with multiple projects, the same service can be registered many times as different projects each add their dependencies. The result is multiple identical descriptors in the container - wasted allocations at best, and unexpected behavior at worst.
Install
Install-Package RzR.Extensions.UniqueServiceCollection
The package depends only on Microsoft.Extensions.DependencyInjection.Abstractions.
Quick start
using RzR.Extensions.UniqueServiceCollection.ServiceCollectionExtensions;
// Last-wins: remove any existing IMyService registration, then add this one.
services.AddUnique<IMyService, MyService>();
// First-wins: add only if IMyService is not already registered.
services.RegisterIfNotExist<IMyService, MyService>();
// Replace: same as AddUnique, but returns true when a prior registration existed.
bool replaced = services.ReplaceUnique<IMyService, MyServiceV2>();
// Fluent chaining - all AddUnique* and RegisterIfNotExist* methods return IServiceCollection.
services
.AddUnique<IServiceA, ServiceA>()
.AddUnique<IServiceB, ServiceB>(ServiceLifetime.Scoped)
.RegisterIfNotExist<IServiceC, ServiceC>();
// Startup guardrail - throws InvalidOperationException if exact duplicates exist.
services.ValidateNoDuplicates();
Two registration strategies
| Method group | Strategy | Wins |
|---|---|---|
AddUnique* |
Remove all existing registrations for the type, then add the new one | Last registration |
RegisterIfNotExist* |
Add only when no registration for the type exists yet | First registration |
Choose AddUnique* when you want to guarantee a specific implementation is used regardless of registration order. Choose RegisterIfNotExist* when you want a default that callers can override by registering first.
What counts as a duplicate
A duplicate is a registration that shares the same ServiceType, Lifetime, and implementation identity (same ImplementationType, same ImplementationInstance reference, or same ImplementationFactory reference) as another registration already in the collection.
Intentional multi-registration of distinct implementations of the same interface - the standard IEnumerable<TService> resolution pattern - is not treated as a duplicate and is never removed by the cleanup or validation methods.
Feature highlights
AddUnique<TService, TImplementing>()- type-mapped registration, configurable lifetimeAddUnique<TService>(factory)- factory registration, configurable lifetimeAddUnique<TService>(instance)- singleton instance registrationRegisterIfNotExist<TService, TImplementing>()- first-wins registrationReplaceUnique<TService, TImplementing>()- replace and report whether anything was replacedCheckAndCleanUpDuplicateService<TService>()- remove exact duplicates for one typeCheckAndCleanUpAllDuplicates()- remove exact duplicates across all typesFindExactDuplicates()/FindExactDuplicates<TService>()- inspect without mutatingFindServiceDuplicate()/FindServiceDuplicate<TService>()- legacy overloads (count-based)ValidateNoDuplicates()- fail-fast guardrail, suitable for unit tests and CI startup checks
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 3.1.32)
- RzR.Core.CodeSource (>= 6.0.0.94)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.0.0.8109 | 94 | 6/9/2026 |