【问题标题】:Ninject Binding Generic and Specific Interfaces to Same ImplementationNinject 将通用和特定接口绑定到相同的实现
【发布时间】:2014-06-04 14:47:03
【问题描述】:

有没有更简单的方法让 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

【问题讨论】:

    标签: .net vb.net ninject


    【解决方案1】:

    两种绑定都是必需的,但您可以使用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);
        }
    }
    

    【讨论】:

      最近更新 更多