Skip to content

Instantly share code, notes, and snippets.

@gusarov
Last active December 23, 2024 20:22
Show Gist options
  • Save gusarov/ca587260923c606590994299d7bad60f to your computer and use it in GitHub Desktop.
Save gusarov/ca587260923c606590994299d7bad60f to your computer and use it in GitHub Desktop.
Resolve keyed service by name with convenient generic interface with double arity match
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
var appBuidler = Host.CreateApplicationBuilder();
appBuidler.Services.AddKeyedSingleton<IService, Serivce1>("abc");
appBuidler.Services.AddKeyedSingleton<IService, Serivce2>("def");
appBuidler.Services.AddSingleton<Test>();
appBuidler.Services.AddSingleton(typeof(IReadOnlyDictionary<,>), typeof(NamedKeyResolver<,>));
var app = appBuidler.Build();
Console.WriteLine(app.Services.GetRequiredKeyedService<IService>("abc"));
Console.WriteLine(app.Services.GetRequiredKeyedService<IService>("def"));
foreach (var item in app.Services.GetServices<IService>())
{
Console.WriteLine(item.GetType().Name);
}
app.Services.GetServices<Test>();
interface IService
{
}
class Serivce1 : IService
{
}
class Serivce2 : IService
{
}
class Test
{
public Test(IReadOnlyDictionary<string, IService> services)
{
Console.WriteLine(services["abc"].GetType().Name);
Console.WriteLine(services["def"].GetType().Name);
}
}
class NamedKeyResolver<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>
{
private readonly IServiceProvider _keyedServiceProvider;
public NamedKeyResolver(IServiceProvider keyedServiceProvider)
{
_keyedServiceProvider = keyedServiceProvider;
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public TValue this[TKey key]
{
get
{
TryGetValue(key, out var value);
if (value == null)
{
throw new KeyNotFoundException(key?.ToString());
}
return value;
}
}
public IEnumerable<TKey> Keys => throw new NotImplementedException();
public IEnumerable<TValue> Values => throw new NotImplementedException();
public int Count => throw new NotImplementedException();
public bool ContainsKey(TKey key)
{
return TryGetValue(key, out _);
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
throw new NotImplementedException();
}
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
{
value = _keyedServiceProvider.GetKeyedService<TValue>(key);
return value != null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment