2013-09-20 2 views
3

У меня есть набор из 15-20 классов, которые зависят от класса, который реализует общий интерфейс с параметрами связанного типа. Интерфейс выглядит следующим образом:Как связать одну реализацию с несколькими расширенными интерфейсами в Guice?

interface Handler<F extends Foo, T extends Foo> { 
    T handleFoo(String methodName, F myFoo); 
} 

И один реализацию Хэндлер, которая использует отражение, чтобы иметь дело со всеми специализированными случаями Foo, потому что все они «похожи, но разные».

class ConcreteHandler<Foo, Foo> implements Handler<Foo, Foo> { 
    T handleFoo(String methodName, F foo) { 
     // do your thing 
    } 
} 

Я хотел бы, чтобы иметь возможность использовать этот класс таким образом типобезопасного в своих сотрудников, как:

@Inject ACollaborator(Handler<Bar, Baz> barHandler) {...} 

где Bar и Baz как продлить Foo. К сожалению, Guice жалуется, что Handler<Bar, Baz> не обязан, когда я пытаюсь это в моем модуле:

bind(new TypeLiteral<Handler<? extends Foo, ? extends Foo>>() {}).to(ConcreteHandler.class); 

Я также попытался следующие, который вызывает ошибку компиляции, поскольку ConcreteHandler не подкласс Handler<Bar, Baz>:

bind(new TypeLiteral<Handler<Bar, Baz>>() {}).to(ConcreteHandler.class); 

У меня так много таких объектов Collaborator, что я не увлекаюсь мыслью о реализации Handler для каждой комбинации типов и помещением для них 20 отдельных операторов привязки.

Как выполнить то, что я пытаюсь с помощью Guice, который связывает одну конкретную реализацию с одним интерфейсом с различными универсальными параметрами?

+1

Вы имели в виду 'bind (new TypeLiteral >() {}). to (ConcreteHandler.class); '? –

+0

Да, благодарю вас за это, @PaulBellora. – Jonathan

ответ

2

Вы можете это сделать, создав TypeLiteral, представляющий цель привязки, возможно, с необработанным типом.

Вы увидите пример того, как сделать это в этом вопросе: Reconstructing generic types at runtime with Guice via Types and TypeLiterals

В основном то, что вы будете потребности что-то построить ключ каждого обработчика <> вы хотите связать.

Тогда вы можете сказать что-то вроде:

bindHandler(Bar.class, Baz.class); 

Который будет:

  1. создать TypeLiteral<ConcreteFoo<Bar, Baz>>
  2. создайте TypeLiteral<Foo<Bar, Baz>>
  3. BIND последнего к бывшему

Также я думаю, что в вашем примере ConcreteHandler должен реализовывать Handler [?]

+0

Вы правы насчет упущения предложения Конкретного Хэндлера. Благодарю. Я дам ваше предложение выстрелу и отчитаю. – Jonathan

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