I'm trying to use dependency injection to add a generic service that has constructor parameters. I Need to implement this, generically:
host.Services.AddSingleton<IService>(x =>
new Service(x.GetRequiredService<IOtherService>(),
x.GetRequiredService<IAnotherOne>(),
""));
This is what I have working with open generics:
host.Services.AddSingleton(typeof(IGenericClass<>), typeof(GenericClass<>));
I have not been able to add constructor params with opengenerics. This is the class I want to add DI:
public class GenericClass<T> : IGenericClass<T> where T : class, new()
{
private readonly string _connectionString;
private readonly IGenericClass2<T> _anotherGenericInterface;
private readonly IInterface _anotherInterface;
public GenericClass(
string connectionString,
IGenericClass2<T> anotherGenericInterface,
IInterface anotherInterface)
{
_connectionString = connectionString ??
throw new ArgumentNullException(nameof(connectionString));
_executer = anotherGenericInterface;
_sproc = anotherInterface;
}
}
With MS.DI, it's impossible to construct an open-generic registration using a factory method, just as you did with the IService
registration.
The solution here is to wrap all primitive constructor values into a Parameter Object, so the DI Container can resolve it as well. For instance:
// Parameter Object that wraps the primitive constructor arguments
public class GenericClassSettings
{
public readonly string ConnectionString;
public GenericClassSettings(string connectionString)
{
this.ConnectionString =
connectionString ?? throw new ArgumentNullExcpetion();
}
}
The GenericClass<T>
's constructor can now depend on the new Parameter Object:
public GenericClass(
GenericClassSettings settings,
IGenericClass2<T> anotherGenericInterface,
IInterface anotherInterface)
{
_connectionString = settings.ConnectionString;
_executer = anotherGenericInterface;
_sproc = anotherInterface;
}
This allows you to register both the new parameter object and the open-generic class:
host.Services.AddSingleton(new GenericClassSettings("my connection string"));
host.Services.AddSingleton(typeof(IGenericClass<>), typeof(GenericClass<>));