Round #720

10 May 2026, 15:13· csharp· Meta-Llama-3.3-70B-Instruct· r13-clean-hints
Complexity
band 0
ZP / UO / OBS
3 / 0 / 2
Journey weight
285
Lightshift ΔL

Prompt

Use Keyed services (Microsoft.Extensions.DependencyInjection 8.0) to register multiple implementations of an interface and resolve by string key.

Zero-point index (what the engine surfaced)

ZPI-ZPI-0019 | 2026-05-10T15:13:33Z Use Keyed services (Microsoft.Extensions.DependencyInjection 8.0) to register multiple implementations of an interface and resolve by string key. ZERO POINT — 3 entries (structural invariants) ● hsl(7.18, 100%, 50%) class [feature] ● hsl(0.00, 100%, 50%) public [feature] ● hsl(84.10, 100%, 50%) namespace [feature] UNOBSERVED — 0 entries (implied truths) OBSERVED — 2 entries (explicit in request) ◉ hsl(9.23, 100%, 50%) interface [feature] ◉ hsl(133.33, 100%, 15%) string [feature] COMPLEXITY │ 5 entries │ spread: 124° │ band: LOW

Baseline response (no ZPI)

Here's an example of how you can use keyed services in Microsoft.Extensions.DependencyInjection 8.0 to register multiple implementations of an interface and resolve them by a string key. Let's assume we have an interface `ILogger` with two implementations: `ConsoleLogger` and `FileLogger`. ```csharp public interface ILogger { void Log(string message); } public class ConsoleLogger : ILogger { public void Log(string message) { Console.WriteLine($"Console: {message}"); } } public class FileLogger : ILogger { public void Log(string message) { // Simulating file logging Console.WriteLine($"File: {message}"); } } ``` To register these implementations with keyed services, you can use the `AddService` method with a key. ```csharp using Microsoft.Extensions.DependencyInjection; public class Program { public static void Main() { var serviceProvider = BuildServiceProvider(); // Resolve the console logger var consoleLogger = serviceProvider.GetService<ILogger>("console"); consoleLogger?.Log("Hello from console logger"); // Resolve the file logger var fileLogger = serviceProvider.GetService<ILogger>("file"); fileLogger?.Log("Hello from file logger"); } private static IServiceProvider BuildServiceProvider() { var services = new ServiceCollection(); // Register the console logger with the key "console" services.AddService<ILogger>("console", _ => new ConsoleLogger()); // Register the file logger with the key "file" services.AddService<ILogger>("file", _ => new FileLogger()); return services.BuildServiceProvider(); } } ``` In this example, we're registering the `ConsoleLogger` and `FileLogger` classes with the `ILogger` interface using the `AddService` method. We're passing a key ("console" or "file") and a factory method that creates an instance of the logger. When we want to resolve a logger, we use the `GetService` method and pass the key to get the corresponding logger instance. Note that if you try to resolve a logger with a key that doesn't exist, the `GetService` method will return `null`. You can use the null-conditional operator (`?.`) to safely call methods on the resolved logger instance. Also, keep in mind that keyed services are not the same as named services. Named services are a legacy feature that's been replaced by keyed services in .NET 8.0. If you're upgrading from an older version of .NET, you might need to update your code to use keyed services instead.

Enhanced response (with ZPI)

### Registering Multiple Implementations of an Interface To register multiple implementations of an interface and resolve them by a string key, you can use the `TryAddScoped` or `TryAddTransient` methods provided by the `IServiceCollection` interface in the `Microsoft.Extensions.DependencyInjection` namespace. Here's an example implementation: ```csharp using Microsoft.Extensions.DependencyInjection; // Define the interface public interface IMyService { string GetMessage(); } // Implementations of the interface public class MyServiceA : IMyService { public string GetMessage() { return "Message from A"; } } public class MyServiceB : IMyService { public string GetMessage() { return "Message from B"; } } public class MyServiceC : IMyService { public string GetMessage() { return "Message from C"; } } class Program { static void Main(string[] args) { // Create a new service collection var services = new ServiceCollection(); // Register multiple implementations of the interface services.TryAddScoped<IMyService>("A", _ => new MyServiceA()); services.TryAddScoped<IMyService>("B", _ => new MyServiceB()); services.TryAddScoped<IMyService>("C", _ => new MyServiceC()); // Build the service provider var serviceProvider = services.BuildServiceProvider(); // Resolve the services by key var serviceA = serviceProvider.GetService<IMyService>("A"); var serviceB = serviceProvider.GetService<IMyService>("B"); var serviceC = serviceProvider.GetService<IMyService>("C"); // Use the resolved services Console.WriteLine(serviceA?.GetMessage()); // Output: Message from A Console.WriteLine(serviceB?.GetMessage()); // Output: Message from B Console.WriteLine(serviceC?.GetMessage()); // Output: Message from C } } ``` ### Explanation In this example, we define an interface `IMyService` with a method `GetMessage()`. We then create three implementations of this interface: `MyServiceA`, `MyServiceB`, and `MyServiceC`. To register these implementations, we use the `TryAddScoped` method, which adds a scoped service of the specified type to the services container. We pass the interface type `IMyService` and a string key as arguments. The key is used to identify the specific implementation to resolve. We then build the service provider using the `BuildServiceProvider` method and resolve the services by their keys using the `GetService` method. Note that the `GetService` method returns `null` if the service is not found, so we use the null-conditional operator (`?.`) to safely call the `GetMessage` method on the resolved services. This approach allows you to register multiple implementations of an interface and resolve them by a string key, making it easy to manage and switch between different implementations of a service.

Grader chain

Each grader reads the same baseline + enhanced pair and casts an independent verdict. Disagreement is the framework's own signal — not noise to be averaged away.

V1samba/Meta-Llama-3.3-70B-Instruct
Better
V4qwen2.5-coder-3b-instruct
Better
V5openrouter/qwen/qwen3-235b-a22b-2507
Better
V7qwen2.5-coder-7b-instruct
Better
V8openai/gpt-4.1
Worse
V9anthropic/claude-opus-4-7
Worse
V12openai/gpt-4o
Better

Comments

Our grader said what it said. What do you say? Comment as a guest below.

No comments yet. Be the first to say what you make of this round.

← back to all rounds