Guice可以根据参数自动创建不同类的实例吗? [英] Can Guice automatically create instances of different classes based on a parameter?

查看:88
本文介绍了Guice可以根据参数自动创建不同类的实例吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标准对象工厂可能如下所示:

A standard object factory may look like this:

interface I { ... }
class A implements I { ... }
class B implements I { ... }

class IFactory {
    I getI(int i) {
        switch (i) {
        case 1: return new A();
        default: return new B();
        }
    }
}

是否可以设置绑定,所以为我完成切换,即我所做的是调用getInstance或注入?我正在寻找辅助注射,但似乎是不同的主题: https:// code .google.com / p / google-guice / wiki / AssistedInject

Is it possible to set up bindings so that switch is done for me, i.e. all I do is call getInstance or inject? I was looking at assisted injection but that seems to be different topic: https://code.google.com/p/google-guice/wiki/AssistedInject

推荐答案



MapBinder ,这是 Multibindings 功能。请注意,您仍然需要使用某种 IFactory 或其他工厂界面,因为 getInstance 不会以 getI 的方式采取参数,您仍然需要建立从整数到类实现之间的映射。

It sounds like you're looking for a MapBinder, which is part of the Multibindings feature. Note that you'll still need to put in some kind of IFactory or other factory interface, because getInstance doesn't take a parameter the way your getI does, and you'll still need to establish a mapping from integer to class implementation somewhere.

class IModule extends AbstractModule {
  @Override public void configure() {
    MapBinder<Integer, I> myBinder =
        MapBinder.newMapBinder(binder(), Integer.class, I.class);
    myBinder.addBinding(1).to(A.class);
    // Add more here.
  }
}

// You can even split the MapBinding across Modules, if you'd like.
class SomeOtherModule extends AbstractModule {
  @Override public void configure() {
    // MapBinder.newMapBinder does not complain about duplicate bindings
    // as long as the keys are different.
    MapBinder<Integer, I> myBinder =
        MapBinder.newMapBinder(binder(), Integer.class, I.class);
    myBinder.addBinding(3).to(C.class);
    myBinder.addBinding(4).to(D.class);
  }
}

配置有这些模块的注射器将提供可注射的 Map< Integer,I> 具有一切绑定的实例;在这里,它将是一个三入门的地图,从1到完全注入 A 实例,从3到 C 实例,从4到 D 实例。这实际上是一个改进,例如使用新的关键字,因此没有将任何依赖项注入到 A B

An injector configured with those modules will provide an injectable Map<Integer, I> that has an instance of everything bound; here it would be a three-entry map from 1 to a fully-injected A instance, from 3 to a C instance, and from 4 to a D instance. This is actually an improvement over your switch example, which used the new keyword and thus didn't inject any dependencies into A or B.

为了更好的选项不会创建这么多浪费的实例,请注入<$该MapBinder还自动提供c $ c> Map< Integer,Provider< I> 。使用它像这样:

For a better option that doesn't create so many wasted instances, inject a Map<Integer, Provider<I>> that MapBinder also provides automatically. Use it like this:

class YourConsumer {
  @Inject Map<Integer, Provider<I>> iMap;

  public void yourMethod(int iIndex) {
    // get an I implementor
    I i = iMap.get(iIndex).get();
    // ...
  }
}

提供一个默认实现(和不透明的界面),但是,您将需要在 MapBinder 映射之上实现自己的简短包装:

To provide a "default" implementation (and opaque interface) the way you did, though, you'll want to implement your own short wrapper on top of the MapBinder map:

class IFactory {
  @Inject Map<Integer, Provider<I>> iMap;
  @Inject Provider<B> defaultI; // Bound automatically for every Guice key

  I getI(int i) {
    return iMap.containsKey(i) ? iMap.get(i).get() : defaultI.get();
  }
}



更简单,工厂式



如果上面看起来像是过度的,记住你可以注入注射器 ,并从键到实现创建一个本地 Map 。 (您也可以使用 ImmutableMap ,就像我在这里一样。)

Simpler, factory-style

If the above looks like overkill, remember that you can inject an Injector and create a local Map from key to implementation. (You can also use ImmutableMap like I did here).

class IFactory {
  @Inject Injector injector; // This is a bad idea, except for times like this
  @Inject Provider<B> defaultI;
  static final ImmutableMap<Integer, Class<? extends I>> map = ImmutableMap.of(
      1, A.class,
      3, C.class,
      4, D.class);

  I getI(int i) {
    return map.containsKey(i)
        ? injector.getInstance(map.get(i))
        : defaultI.get();
  }
}

这篇关于Guice可以根据参数自动创建不同类的实例吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆