【问题标题】:How to bind Generic-type interfaces in Ninject如何在 Ninject 中绑定泛型接口
【发布时间】:2012-05-01 21:15:31
【问题描述】:

我对 Ninject 还很陌生,当我开始实现通用存储库模式时,我发现自己陷入了困境。我想将依赖项 IRepository 绑定到类 ConcreteRepository,其中 ConcreteRepository 实现 IRepository 并且 EntityType 实现 IEntityType。我试过这个:

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

...但是 Ninject 不会接受,因为它不知道也不关心 EntityType 实现了 IEntityType。我该如何去绑定这个依赖呢?

更新

这是我得到的错误:

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

解决方案

我仍然不太明白为什么我的绑定不起作用,但显然我在那里错误地使用了泛型。因此,该解决方案与 NInject 并不真正相关。我结束了指定 ConcreteRepository 以将 IEntityType 与 TEntityType 显式连接:

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

那么注入可以写成如下:

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

【问题讨论】:

  • 您收到什么信息?它是编译器还是运行时? ConcreteRepository&lt;EntityType&gt; 是否实现 IRepository&lt;IEntityType&gt; (此外,通常一个人会在 IRepository&lt;EntityType&gt; 上启用 ctor 依赖项 - 在这种情况下,您的 Bind 以上将是错误的。
  • @RubenBartelink 这是一个编译错误;见上面的更新。对于您的第一点 - 它没有,但如前所述 ConcreteRepository 实现了 IRepository。也许这就是我的问题。对于第二点,我想在构造函数中使用 IRepository 以实现灵活性——存储库依赖项应该处理接口,而不是具体实体。
  • 对。那么导致编译错误的where 约束是有原因的——你建议的具体组件类型根本无法转换为你Binding 的服务类型。别找了!我建议看看其他人是如何实现通用存储库模式的——你离正常实践还很远。你可以在这里的问题中解释你从这些东西中得到了什么,但我建议你应该先问自己,然后也许在这里你的类层次结构是否可以合理化。
  • @RubenBartelink 可能是这样,但我的问题不是如何实现通用存储库。这是如何将依赖项绑定到通用接口。
  • @dbaseman 你为什么要你的具体存储库采用一个具体的实体?它不能只占用你的实体接口吗?

标签: c# generics dependency-injection ninject generic-interface


【解决方案1】:
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&lt;IEntity&gt; 绑定到ConcreteRepository&lt;IEntity&gt;,但不适用于ConcreteRepository&lt;ConcreteEntity&gt;。我不确定是否有办法为 Ninject 中的所有类型生成此绑定。要获得这种效果,您需要手动绑定每个存储库。
  • 为混乱道歉——我试图通过抽象来简化我的用例,但我认为这只是混淆了我试图做的事情。我基本上实现了你的建议;只有我添加了第二个类型参数来保留类定义中实体的接口。
  • @dbaseman 我其实很喜欢,这意味着您的具体存储库是抽象构造和具体构造之间的映射