views:

45

answers:

1

Is it possible to wrap generic injections in some way?

Given the interface:

interface IFoo<T>

In my guice module:

bind((Key<IFoo<SomeType>) Key.get(Types.newParameterizedType(IFoo.class, SomeType.class))).to(Foo.class);

But before I return the Foo instance I want to wrap it with this:

class FooWrapper<T> implements IFoo<T> { public FooWrapper(Foo<T> foo) { ... } }

Somewhere like this:

return new FooWrapper<T>(foo);

+1  A: 

Here's one way you can do this:

public class FooModule extends PrivateModule {
  @Retention(RUNTIME) @BindingAnnotation
  private @interface Internal {}

  @Override protected void configure() {
    bind(new TypeLiteral<IFoo<SomeType>>(){}).annotatedWith(Internal.class)
        .to(new TypeLiteral<Foo<SomeType>>(){});
  }

  @Provides @Exposed IFoo<SomeType> provideFoo(@Internal IFoo<SomeType> foo) {
    return new FooWrapper<SomeType>(foo);
  }
}

Another thing that might work well would be to add a general annotation like @Wrapped and then to declare FooWrapper's constructor like this:

@Inject public FooWrapper(@Wrapped IFoo<T> foo) { ... }

Then in your private module you could bind Foo annotated with @Wrapped and bind and expose FooWrapper normally, without needing to use an @Provides method.

There may well be better ways of doing this I haven't thought of yet. Do also keep in mind that method interception is often a good way of decorating interface implementations with other behavior as well.

ColinD
Your answer is correct for my original question, but I realised I should have given more information as it does not solve my problem. Unfortunately you can't use .annotatedWith on a bound Key. Any ideas?
Finbarr
Ignore that comment, I just realised you need to give the annotation class inside Key.get as the second parameter.
Finbarr
@Finbarr: I updated my answer to match your edits to the question, though I used `TypeLiteral` rather than `Key`... but yes, annotations are part of the `Key`.
ColinD