Basically we have a Interface that takes another interface (constrained) When you create a hard implementation of that interface through a base class, the conversion fails as there is no implicit conversion.
I know that was probably hard to follow so we've gone ahead and made the simplest .NET 6 console app possible to show this issue.
Definition:
public interface IClient { }
public abstract class ClientBase : IClient { }
public class Client : ClientBase, IClient { }
public interface IServer<TClient> where TClient : IClient { }
public abstract class ServerBase<TClient>
: IServer<TClient> where TClient : IClient { }
public class Server : ServerBase<Client> { }
Console:
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleApp;
public class Program
{
public static IServiceCollection Services = new ServiceCollection();
public static ServiceProvider Provider;
public static void Main()
{
Services.AddSingleton<IClient, Client>();
Services.AddSingleton<IServer<IClient>, Server>();
Provider = Services.BuildServiceProvider();
var server = Provider.GetService<IServer<IClient>>();
}
}
Server can be type casted to an IServer
Client can be type casted to an IClient
But you cannot implicitly type case a Server instance to an IServer<IClient> even though the base implementations all can be casted to those types.
I'm absolutely confused about this. We can fix it by changing DI to take an IServer<Client> but then one of our services which looks for ALL implementations of IServer<IClient> cannot work anymore since we are providing a concrete implementation.