2016-12-22 3 views
0

Скажем, я хочу создать общего поставщика, который возвращает первый элемент в коллекции. Что-то вроде:Явно добавить зависимость связывания при связывании с экземпляром поставщика Guice

class P extends Provider<T> { 
    private final Provider<Collection<T>> provider; 

    FirstItemProvider(Provider<Collection<T>> provider) { 
    this.provider = provider; 
    } 

    @Override 
    public T get() { 
    Collection<T> input = provider.get(); 
    Iterator<T> iter = input.iterator(); 
    return iter.hasNext() ? iter.next() : null; 
    } 
} 

Теперь у меня есть такие различные коллекции с различными примечаниями, и я хочу, чтобы добавить привязки к этому провайдеру, но я также хочу, чтобы иметь возможность пройти привязки с помощью DefaultBindingTargetVisitor и getDependencies().

Я пытался что-то вроде:

bind(Key.get(type, annotation)) 
    .toProvider(new P(
    getProvider(
     Key.get(Types.collectionOf(type.getType()), annotation) 
    ) 
)); 

Это прекрасно работает в условиях связывания, но обход не вок, как Guice не обнаруживает зависимость.

Я не мог найти другого способа привязки к аннотированному продюсеру, так как на нем нет аннотации.

Есть ли способ сделать то, что я пытаюсь сделать?

Благодаря Yaron

+0

Возможно, есть '' P' реализовать HasDependencies'? Не проверял. –

+0

IIRC HasDependencies - это связующий интерфейс, не связанный с провайдерами, а код просто сканирует провайдера для точек впрыска, поэтому он не будет работать. Я еще раз взгляну на исходный код, чтобы убедиться. – Yaron

+0

Вот пример того, что я думаю: https://github.com/google/guice/blob/master/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider.java#L165 –

ответ

2

Это работает для меня:

import java.util.Arrays; 
import java.util.Collection; 
import java.util.Collections; 
import java.util.List; 
import java.util.Set; 

import javax.inject.Provider; 

import com.google.inject.AbstractModule; 
import com.google.inject.Binder; 
import com.google.inject.Guice; 
import com.google.inject.Injector; 
import com.google.inject.Key; 
import com.google.inject.name.Names; 
import com.google.inject.spi.Dependency; 
import com.google.inject.spi.ProviderInstanceBinding; 
import com.google.inject.spi.ProviderWithDependencies; 

class FirstItemProvider<T> implements ProviderWithDependencies<T> { 
    private final Provider<? extends Collection<? extends T>> collectionProvider; 
    private final Key<? extends Collection<? extends T>> key; 

    public FirstItemProvider(Binder binder, Key<? extends Collection<? extends T>> key) { 
     this.collectionProvider = binder.getProvider(key); 
     this.key = key; 
    } 

    @Override 
    public T get() { 
     return collectionProvider.get().iterator().next(); 
    } 

    @Override 
    public Set<Dependency<?>> getDependencies() { 
     return Collections.<Dependency<?>>singleton(Dependency.get(key)); 
    } 
} 

class FooModule extends AbstractModule { 
    @Override 
    protected void configure() { 
     Key<List<String>> listKey = new Key<List<String>>(Names.named("foo")){}; 
     Key<String> stringKey = new Key<String>(Names.named("foo")){}; 

     bind(listKey).toInstance(Arrays.asList("foo", "bar")); 
     bind(stringKey).toProvider(new FirstItemProvider<>(binder(), listKey)); 
    } 
} 

public class Foo { 
    public static void main(String[] args) { 
     Injector injector = Guice.createInjector(new FooModule()); 

     Key<String> stringKey = new Key<String>(Names.named("foo")){}; 
     ProviderInstanceBinding<String> binding = (ProviderInstanceBinding<String>)injector.getBinding(stringKey); 
     System.out.println(binding.getDependencies()); 
    } 
} 

Выход

[Key[type=java.util.List<java.lang.String>, [email protected](value=foo)]] 
+0

Пришло время попробовать, но это действительно работает! большое спасибо! – Yaron

Смежные вопросы