A really interesting trick you can do with the ASP.NET core dependency injection is that you can register an open generic type. The prime example is the ILogger interface that is built in. Each class can inject a ILogger of its type without having to register it specifically. It can be quite a powerful technique in the right circumstance.
Imagine I have a message queue implementation that I think is pretty solid but different queues have different concrete types. I could create something like:
public interface IMessageQueue<T>
{
IAsyncEnumerable<T> Get();
}
public class MessageQueue<T> : IMessageQueue<T>
{
private readonly Channel<string> _fakeInternalQueue =
Channel.CreateUnbounded<string>();
public async IAsyncEnumerable<T> Get()
{
while (true)
{
await _fakeInternalQueue.Reader.WaitToReadAsync();
string message = await _fakeInternalQueue.Reader.ReadAsync();
yield return JsonSerializer.Deserialize<T>(message);
}
}
}
I could register it as:
services.AddSingleton(typeof(IMessageQueue<>), typeof(MessageQueue<>));
Then all I would need to do to use it with a concrete type of MyClass is to add it into the Constructor as:
public MyService(IMessageQueue<MyClass> messageQueue)
{
this.messageQueue = messageQueue;
}