注入一个注入实例列表

Inject a list of injected instances

我有一个公开方法的服务。我有一个该方法的实现,可以聚合同一服务的其他实现的结果。如何通过注入将其他实现列表注入到聚合实现中?例如:

我有一个特性 DictionaryProvider,它提供了 get( s: String ) 方法。我的 MultipleDictionaryProvider 实现可以聚合其他实现,例如 OxfordDictionaryAndColorProviderWebsterDictionaryAndShapeProvider

    class OxfordDictionaryAndColorProvider (p: Param ) extends DictionaryProvider with ColorProvider
    class WebsterDictionaryAndShapeProvider extends DictionaryProvider with ShapeProvider

    class MultipleDictionaryProvider( 
         l: List[ DictionaryProvider ]
    )
    {
            def get(){ /*Sequence of l matters*/  }
    }
    extends DictionaryProvider

OxfordDictionaryAndColorProviderWebsterDictionaryAndShapeProvider都是通过注入构造的。它们在提供字典之外都有一些作用,并且它们无论如何都构造了一个单例实例,分别作为 ColorProviderShapeProvider

我想将我的 DictionaryProvider 绑定到 MultipleDictionaryProvider。我应该怎么做才能使 l 里面的元素顺序可以如我所愿? (对于这种特殊情况,OxfordDictionaryAndColorProvider 后跟 WebsterDictionaryAndShapeProvider)(顺序应该很容易更改,并且只需要在一个地方更改)

编辑:我对问题进行了编辑以使其更清楚。

如果您使用的是 Guice,并且您有一个固定的 DictionaryProvider 对象列表,一个简单的方法是简单地将 DictonaryProvider 绑定到 MultipleDictionaryProvider,并在List[DictionaryProvider]:

的注入器模块
@Provides
def makeProviderList(
        oxford: OxfordDictionaryProvider,
        webster: WebsterDictionaryProvider): List[DictionaryProvider] =
    List(oxford, webster)

Guice 将实例化 OxfordDictinaryProviderWebsterDictionaryProvider,调用您的提供程序方法,并使用返回的列表实例化 MultipleDictionaryProvider

如果您想避免在提供者函数签名中使用特定的 class 名称,一个有用的技术是使用带注释的类型,例如 @Named:

@Provides
def makeProviderList(
    @Named("oxford") oxford: DictionaryProvider,
    @Named("webster") webster: DictionaryProvider) = List(oxford, webster)

虽然这段代码似乎仍然包含很多特定于字典的信息,但实际上并未指定实现 classes,它们需要像这样绑定在模块 class 中:

bind(classOf[DictionaryProvider])
    .annotatedWith(Names.named("oxford"))
    .to(classOf[OxfordDictionaryProvider])

词典的数量和种类仍然是硬编码的。为了使其更加灵活,您需要自己动手进行实例化:

val dictList = List("oxford", "webster")

@Provides
def makeProviderList(injector: Injector) =
    dictList.map(dictName => injector.getInstance(
        Key.get(classOf[DictionaryProvider], Names.named(dictName))))

请注意,dictList 可能在运行时确定,甚至可能使用此绑定注入:

bind(Key.get(new TypeLiteral[List[String]](){}))
    .toInstance(List("oxford", "webster"))