简体   繁体   中英

How can I write a generic FactoryModuleBuilder?

I'd like to know how to represent a generic version of the following binding that won't fail with xxx cannot be used as a key it is not fully specified

install(new FactoryModuleBuilder().
   implement(new TypeLiteral<SomeClass<T,?>>(){}, 
      new TypeLiteral<SomeOtherClass<T, U>>(){}).
   build(SomeFactory.class);

It seems that the implement method isn't available with a parameterized type parameter.

This is not possible because of the way Guice uses type literal parameters. TypeLiterals require concrete types and, as you see from the exception, cannot accept generic parameters.

To quote @jesse-wilson

Note that Guice doesn't allow bindings for types that aren't fully-qualified. For example, you can bind a Map<String, Integer> but you can't bind a Map<K, V> . https://stackoverflow.com/a/1117878/654187

You can "fully qualify" these bindings as described here: https://stackoverflow.com/a/1120990/654187

But I doubt this is what you want.

The good news is you can still write this factory without assisted injection easily:

public class SomeFactory{
    @Inject
    private SomeDependency someDependency;

    public <T> SomeClass<T, ?> buildSomeClass(T t){
        return new SomeOtherClass<T, Object>(t, someDependency);
    }
}

Alen Vrečko posted :

Imho the best you can do with generics is something like

install(new Assist2<Payment, RealPayment>(PaymentFactory.class){}); or

install(new Assist3<SomeClass<Foo, Bar>, SomeOtherClass<Foo, Bar>, SomeFactory<Foo>(){});

Should be pretty easy to implement this approach. Just look in the source of TypeLiteral.

If you absolutely need type parameters something like:

install(new CustomAssist<Baz>(){}); where

CustomAssist<T> extends Assist<SomeClass<Foo,T>,SomeOtherClass<Foo,Bar>{...

might be possible but not trivial to implement. But a lot of fun.

To follow on from @johncarl

If you are just injecting someDependency then you'll be getting the instance when the factory is created. To make it work like a FactoryModuleBuilder constructed factory you'll need to inject the Injector

public class SomeFactory{
    @Inject
    private Injector injector;

    public <T> SomeClass<T, ?> buildSomeClass(T t) {
        return new SomeOtherClass<T, Object>(t, injector.getInstance(SomeDependency));
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM