如何在Ninject中绑定泛型接口

23

我对Ninject还比较新,当我尝试实现通用仓储模式时遇到了困难。我想将依赖项IRepository<IEntityType>绑定到一个类ConcreteRepository<EntityType>,其中ConcreteRepository<T>实现了IRepository<T>,而EntityType实现了IEntityType。我尝试了以下代码:

kernel.Bind<IRepository<IEntityType>>().To<ConcreteRepository<EntityType>>();

...但 Ninject 拒绝了它,因为它不知道也不关心 EntityType 实现了 IEntityType。我该如何绑定这个依赖项呢?

更新

这是我收到的错误消息:

错误 3 类型“ICM.Dependency.Repository.ConcreteRepository”不能用作泛型类型或方法“Ninject.Syntax.IBindingToSyntax.To()”中的类型参数“TImplementation”。从“ConcreteRepository<EntityType>”到“IRepository<IEntityType>”没有隐式引用转换。

解决方案

我仍然不太明白我的绑定为什么不起作用,但显然我在那里错误地使用了泛型。 因此,解决方案与 NInject 没有实际关系。 我最终指定了 ConcreteRepository,以明确将 IEntityType 与 TEntityType 连接起来:

public class ConcreteRepository<TInterface, TEntity> : IRepository<TInterface> where TEntity : TInterface { ... }

然后,注入可以编写如下:
kernel.Bind<IRepository<IEntityType>>().To<ConcreteRepository<IEntityType,EntityType>>()

你收到了什么信息?是编译时的还是运行时的?ConcreteRepository<EntityType> 实现了 IRepository<IEntityType> 吗?(通常情况下,构造函数的依赖项应该是 IRepository<EntityType>,在这种情况下,你上面的绑定是错误的。) - Ruben Bartelink
@RubenBartelink 这是一个编译错误;请参见上面的更新。关于你提出的第一点-它确实不是,但是正如我所提到的,ConcreteRepository<T> 实现了 IRepository<T>。也许这就是我的问题所在。对于你提出的第二点,我想在构造函数中使用 IRepository<IEntityType> 以实现灵活性 - 存储库依赖项应处理接口,而不是具体实体。 - McGarnagle
好的。导致编译错误的“where”约束是有原因的 - 您建议的具体组件类型根本无法转换为您要绑定到的服务类型,因此停止查找!我建议查看其他人如何实现通用存储库模式-您离正常实践还很远。您可以在问题中解释一下这些内容给你带来的什么,但我建议您先自问,然后再问问这里是否可以合理化您的类层次结构。 - Ruben Bartelink
@RubenBartelink 可能是这样,但我的问题不是如何实现通用存储库。而是如何将依赖项绑定到通用接口。 - McGarnagle
@dbaseman,为什么您希望具体的存储库完全接受具体实体?它不能只接受实体接口吗? - undefined
显示剩余2条评论
1个回答

47
kernel.Bind(typeof(IRepository<>)).To(typeof(SimpleRepository<>));

如果您想参考,可以看一下我的这个:http://blog.staticvoid.co.nz/2011/10/staticvoid-repository-pattern-nuget.html,里面有绑定的示例。

编辑:

您得到的错误提示表明您的具体存储库不是您要绑定到的泛型存储库的实例,您需要执行以下操作:

public class ConcreteRepository<ConcreteEntity> : IRepository<IEntity>{}

public class ConcreteRepository<ConcreteEntity> : IRepository<ConcreteEntity>{}

@RubenBartelink 嗯,我明白你的意思了。问题在于上述情况适用于将 IRepository<IEntity> 绑定到 ConcreteRepository<IEntity>,但不适用于将 IRepository<IEntity> 绑定到 ConcreteRepository<ConcreteEntity>。我不确定是否有一种方法可以在 Ninject 中为所有类型生成此绑定。要获得此效果,您需要手动绑定每个存储库。 - undefined
抱歉造成困惑——我试图通过抽象化来简化我的用例,但我认为这只是使我尝试做的事情更加难懂了。基本上,我实现了您建议的内容;只是我在类定义中添加了第二个类型参数以保留对实体接口的引用。 - McGarnagle
@dbaseman 我其实很喜欢这个,它意味着你的具体存储库是抽象构造和具体构造之间的映射。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接