I have some service classes which inherit all from the same non generic interface.
But some services will not directly inherit it but through some intermediate generic interface.
Using .NET 6
public interface IService { }
public interface IServiceDirect {}
public class ServiceDirect: IServiceDirect {}
public interface IGenericInterface<T>: IService{}
public abstract class AGenericClass<T>: IGenericInterface<T> {}
public class GenericClass: IGenericInterface<MyEntity> {}
I now have the need to get all services which inherit from IService during runtime.
Unfortunately calling _serviceProvider.GetServices<IService>() will only return the services which inherit directly (meaning only through non generic interfaces like ServiceDirect) from IService
Here is how I register the services (assembly is just an Assembly provided through a parameter) and I left out some code to select only the classes/interfaces I want.
assembly.ExportedType.ToList().ForEach(x => {
//services is of type IServiceCollection
services.AddScoped(x.Parent.IsGenericType
? x.Parent.GenericTypeDefinition()
.MakeGenericType(x.Parent.GetGenericArguments())
: x.Parent, x.Class);
}
So far so good, they get injected and can be resolved when constructor injecting them by their most direct interface or abstract parent (exactly what I usually need).
To resolve them with _serviceProvider.GetServices<IService>() I have to add a second registration like this in my ForEach
assembly.ExportedType.ToList().ForEach(x => {
if(x.Parent.IsGenericType)
{
services.AddScoped(x.Parent.GenericTypeDefinition()
.MakeGenericType(x.Parent.GetGenericArguments())
.GetInterfaces().FirstOrDefault(x => x == typeof(IService)),
x.Class);
}
//services is of type IServiceCollection
services.AddScoped(x.Parent.IsGenericType
? x.Parent.GenericTypeDefinition().MakeGenericType(
x.Parent.GetGenericArguments())
: x.Parent, x.Class);
}
Now I can resolve all the services like I need.
My question is: is there a better way instead of registering every interface I need explicitly?