Please help me to understand why the following code works and why do I get System.ArgumentException: 'Cannot instantiate implementation type 'Concrete1[TOther]' for service type 'IInterface1[System.String]'.' if I uncomment the only commented line.
using Microsoft.Extensions.DependencyInjection.Extensions;
using Scrutor;
public interface IInterface { }
public interface IInterface<T> where T : class { }
public abstract class AbstractClass<T> : IInterface<T>, IInterface where T : class { }
public class Concrete<TOther> : AbstractClass<string> { }
internal class Program
{
private static void Main(string[] args)
{
var services = new ServiceCollection();
services.Scan(x =>
{
x.FromApplicationDependencies(a => true)
.AddClasses(t => t.AssignableTo(typeof(IInterface<>)))
.UsingRegistrationStrategy(RegistrationStrategy.Replace())
//.As(type => type.GetInterfaces().Where(v => v.IsGenericType && v.GetGenericArguments().Length == 1).ToArray())
.AsSelf()
.WithLifetime(ServiceLifetime.Scoped);
});
var sp = services.BuildServiceProvider();
}
}
Concrete<TOther>is a generic type which can't be constructed without passing generic type parameter, i.e. something likeConcrete<string>which can't be done by the DI. Basically your registration will be analogous to:So when user will resolve
IInterface<string>(sp.CreateScope().ServiceProvider.GetService<IInterface<string>>()) the provider should be able to do something likenew Concrete<>which obviously is not possible.Build-in DI container allows registering open generic services with open generic implementations, something like:
But this requires concrete to be declared as:
If it suits your needs then you can mimic that with Scrutor next way:
It breaks the program because it tries to register closed generic service
IInterface<string>as open generic type which is impossible.