为通用类型实现 ninject 提供程序
Implementing ninject provider for a generic type
使用 ninject,我想为 MyRepository
class 创建一个提供程序,它依赖于 ApplicationDbContext
:
public class MyRepository<TEntity> : IMyRepository<TEntity>
where TEntity : MyBaseEntity
{
private ApplicationDbContext _dbContext;
public MyRepository(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
// ...
}
我看到 this document 解释了应该如何创建提供者,但我不确定:
- 如何将
ApplicationDbConext
参数传递给提供商
- 如何实例化泛型类型
这是我的尝试:
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;
}
}
我不确定是否可以为通用类型创建提供程序。如果不,
有人可以展示如何使用 Factory interface 完成此操作吗?
注意:我已经创建 this code review 解释为什么我需要提供者。
因为在这种情况下目标实现类型是提供者已知的。
然后您可以从所请求的类型中获取通用类型,并使用它来构造所需的实现。
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
是假设实现具有原始示例中的代码所暗示的 public 构造函数。如果不是 public 则可以使用反射来查找构造并调用它。
提供者已在内核中注册
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
kernel.Bind(typeof(IMyRepository<>)).ToProvider(typeof(MyRepositoryProvider)).InRequestScope();
告诉内核在解析抽象时使用提供者
IMyRepository<MyEntity> repository = kernel.Get<IMyRepository<MyEntity>>();
我成功地为我的通用类型创建了一个提供者:
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);
}
}
这就是绑定的样子:
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
kernel.Bind(typeof(IMyRepository<>)).ToProvider(typeof(MyRepositoryProvider<>)).InRequestScope();
使用 ninject,我想为 MyRepository
class 创建一个提供程序,它依赖于 ApplicationDbContext
:
public class MyRepository<TEntity> : IMyRepository<TEntity>
where TEntity : MyBaseEntity
{
private ApplicationDbContext _dbContext;
public MyRepository(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
// ...
}
我看到 this document 解释了应该如何创建提供者,但我不确定:
- 如何将
ApplicationDbConext
参数传递给提供商 - 如何实例化泛型类型
这是我的尝试:
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;
}
}
我不确定是否可以为通用类型创建提供程序。如果不, 有人可以展示如何使用 Factory interface 完成此操作吗?
注意:我已经创建 this code review 解释为什么我需要提供者。
因为在这种情况下目标实现类型是提供者已知的。
然后您可以从所请求的类型中获取通用类型,并使用它来构造所需的实现。
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
是假设实现具有原始示例中的代码所暗示的 public 构造函数。如果不是 public 则可以使用反射来查找构造并调用它。
提供者已在内核中注册
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
kernel.Bind(typeof(IMyRepository<>)).ToProvider(typeof(MyRepositoryProvider)).InRequestScope();
告诉内核在解析抽象时使用提供者
IMyRepository<MyEntity> repository = kernel.Get<IMyRepository<MyEntity>>();
我成功地为我的通用类型创建了一个提供者:
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);
}
}
这就是绑定的样子:
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
kernel.Bind(typeof(IMyRepository<>)).ToProvider(typeof(MyRepositoryProvider<>)).InRequestScope();