Ninject绑定通用和特定接口到相同的实现

时间:2014-06-04 14:47:04

标签: .net vb.net ninject

是否有更简单的方法让Ninject在注入时始终使用最具体的界面?

例如,我有一个通用的存储库接口:

Public Interface IRepository(Of TKey, TEntity As {Class, IEntityKey(Of TKey)})
    Sub Save(entity As TEntity)
    Sub Delete(entity As TEntity)
End Interface

然后,我为某些实体提供了更具体的界面:

Public Interface ISpecificEntityRepository
    Inherits IRepository(Of Integer, SpecificEntity)

    Function DoSomethingSpecial() As SpecificEntity
End Interface

Public Class SpecificEntityRepositoryImpl
   Inherts RepositoryImpl(of Integer, SpecificEntity)
   Implements ISpecificEntityRepository
        Overrides Sub Save(entity As TEntity)
          ' Do something specific here for this entity
        End Sub

        Function DoSomethingSpecial() As SpecificEntity Implements ISpecificEntityRepository.DoSomethingSpecial 
          ' Do something else
        End Function
End Class

此接口继承自通用存储库接口,因此可以始终在其中使用它。

现在在我的Ninject内核中我有绑定:

' The generic repository bindings for all entities
Bind(GetType(IPersistRepository(Of ,))).To(GetType(Repository(Of ,)))

' Specific bindings
Bind(Of IRepository(Of Integer, SpecificEntity)).To(Of SpecificEntityRepositoryImpl)()
Bind(Of ISpecificEntityRepository).To(Of SpecificEntityRepositoryImpl)()

正如您所看到的,特定绑定必须绑定两次。 有没有办法让Ninject始终使用最具体的绑定,所以我需要的是:

 ' The generic repository bindings for all entities
Bind(GetType(IPersistRepository(Of ,))).To(GetType(Repository(Of ,)))

' Specific bindings
Bind(Of ISpecificEntityRepository).To(Of SpecificEntityRepositoryImpl)()

然后可以看出ISpecificEntityRepository继承自IRepository并使用SpecificEntityRepositoryImpl两者都没有明确地将其绑定两次?

我需要这个的原因是因为我希望我的代码始终使用最具体的实现,无论代码是希望注入通用接口还是特定接口。例如,可以为特定实体中的某些实体覆盖通用接口中的方法,并且我总是希望使用特定版本。

这些应该引用相同的实现:

Dim x as ISpecificEntityRepository               ' == SpecificEntityRepositoryImpl
Dim y as IRepository(Of Integer, SpecificEntity) ' == SpecificEntityRepositoryImpl

1 个答案:

答案 0 :(得分:0)

两种绑定都是必需的,但您可以使用convention extension来减少工作量。

有些东西(我使用C#语法,因为我不熟悉VB.net,抱歉):

kernel.Bind(x => x
            .FromThisAssembly()
            .SelectAllClasses()
            .InheritedFrom(typeof(IRepository))
            .BindWith<RepositoryBindingGenerator>());

public class RepositoryBindingGenerator : IBindingGenerator
{
    public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
    {
        // todo: using reflection, get the specific interface type and get T of IRepository<T>
        // then create a binding for both like:

        yield return bindingRoot.Bind(closedGenericRepositoryInterface).To(type);
        yield return bindingRoot.Bind(specificRepositoryInterface).To(type);
    }
}