As part of a meta-class system, I would like to use assistedinject to
create a number of FactoryProviders for different interfaces, and use
mapbinder to hold the factories.
It appears that assistedinject doesn't work well with factory
interfaces that extend other interfaces, and without a parent
interface, it's difficult to put all the factories into a mapbinder.
Is there a simple way out of this conundrum that I'm just
overlooking? Is there another way to accomplish my task?
The detalis are below:
I would like to declare assistedinject factories which extend a
superinterface:
public interface MotorcycleFactory { Motorcycle create(String vin); }
public interface YamahaFactory extends MotorcycleFactory { Yamaha
create(String vin); }
public interface HarleyFactory extends MotorcycleFactory { Harley
create(String vin); }
Then put the resulting factories into a mapbinder:
public void configure() {
MapBunder<String, MotorcycleFactory> f = MapBinder.newMapBinder(binder
(), String.class, MotorcycleFactory.class);
f.addBinding("Harley", HarleyFactory.class);
f.addBinding("Yamaha", YamahaFactory.class);
}
Then I should be able to retrieve the factories from the mapbinder and
operate on them:
class Main {
@Inject MapBinder<String, MotorcycleFactory> factories;
Motorcycle create(String brand, String vin) {
return create(factories.get(brand), vin);
}
Motorcycle create(MotorcycleFactory f, String vin) {
return f.create("abc123");
}
}
Unfortunately, this doesn't work because of an issue with
assistedinject.
In snapshot-20081016, assistedinject appears to require that all
methods of the interface directly match the @AssistedInject
constructor signature of the concrete class. (I would have thought it
would require only the declared methods to match, and then do type
matching on the inherited methods.)
So, with this constructor
@AssistedInject public HarleyImpl(GasTank gasTank, @Assisted String
vin) {..}
this line
bind(HarleyFactory.class).toProvider FactoryProvider.newFactory
(HarleyFactory.class, Harley.class));
yields this error
An exception was caught and reported. Message: Constructor mismatch:
Harley has 1 @AssistedInject constructors, factory HarleyFactory has 2
creation methods
So, I cannot bind the HarleyFactory and YamahaFactory because of the
contradictory requirements of (1) super interface returning
MotorcycleFactory and (2) FactoryProvider requiring matching
constructors. It's odd, because the superinterface for HarleyFactory
(MotorcycleFactory) doesn't even declare itself to return a Harley, so
there's no way I can see for FactoryProvider to find a constructor on
HarleyFactory that creates exactly a MotorcycleFactory.
Is there a way around this issue with assistedinject and super
interfaces so that I can have a common class to use in mapbinder? Is
there a solution by using f.addBinding("Harley").toProvider and adding
another level of indirection? Then I still have the @AssistedInject
issue with inherited super-interfaces.
Is there a better way for me to implement the dispatch logic I need
for the meta-class hierarchies?
I have a worked-up sample case for all of this posted at
http://graflex.org/klotz/2008/11/aimb/aimb.zip
Thank you,
Leigh.