Reputation: 15559
Using ninject, I want to create a provider for MyRepository
class which has dependency on ApplicationDbContext
:
public class MyRepository<TEntity> : IMyRepository<TEntity>
where TEntity : MyBaseEntity
{
private ApplicationDbContext _dbContext;
public MyRepository(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
// ...
}
I have seen this document which explains how the providers should be created, but I am not sure:
ApplicationDbConext
argument to the provider Here is my attempt:
public class MyRepositoryProvider : Provider<MyRepository>
{
protected override MyRepository CreateInstance(IContext context)
{
// how to create a generic instance of type T?
MyRepository myRepository = new MyRepository<T>(/*need ApplicationDbContext*/);
return myRepository;
}
}
I am not certain if it is possible to create a provider for a generic type. If not, can someone show how this can be done using Factory interface?
Note: I have created this code review explaining why I need a provider.
Upvotes: 2
Views: 644
Reputation: 247008
Since in this case the target implementation type is known to the provider.
Then you can get the generic type from the type being requested and use that to construct the desired implementation.
public class MyRepositoryProvider : IProvider {
private ApplicationDbContext _applicationDbContext;
public MyRepositoryProvider(ApplicationDbContext applicationDbContext) {
_applicationDbContext = applicationDbContext;
}
Type Type => typeof(MyRepository<>);
public object Create(IContext context) {
var genericArguments = context.GenericArguments; //TEntity
var genericType = this.Type.MakeGenericType(genericArguments); //MyRepository<TEntity>
//using reflection to do new MyRepository<TEntity>(_applicationDbContext)
return Activator.CreateInstance(genericType, _applicationDbContext);
}
}
Activator
is used here under the assumption that the implementation has a public constructor as implied by the code in the original example. If not public then reflection can be used to find the construct and invoke it.
The provider is registered with the kernel
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
kernel.Bind(typeof(IMyRepository<>)).ToProvider(typeof(MyRepositoryProvider)).InRequestScope();
Which tells the kernel to use the provider when resolving the abstractions
IMyRepository<MyEntity> repository = kernel.Get<IMyRepository<MyEntity>>();
Upvotes: 2
Reputation: 15559
I managed to create a provider for my generic type:
public class MyRepositoryProvider<TEntity> : Provider<IMyRepository<TEntity>>
where TEntity : MyBaseEntity
{
private ApplicationDbContext _applicationDbContext;
public MyRepositoryProvider(ApplicationDbContext applicationDbContext)
{
_applicationDbContext = applicationDbContext;
}
protected override IMyRepository<TEntity> CreateInstance(IContext context)
{
return new MyRepository<TEntity>(_applicationDbContext);
}
}
And this is how the binding looks like:
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
kernel.Bind(typeof(IMyRepository<>)).ToProvider(typeof(MyRepositoryProvider<>)).InRequestScope();
Upvotes: 1