bind dynamically

559 views
Skip to first unread message

francisco treacy

unread,
Aug 20, 2008, 10:39:45 AM8/20/08
to google...@googlegroups.com
hi

i am trying to dynamically bind things in guice. for one type known
beforehand, i would directly:

bind(new TypeLiteral<Service<Car>>() {}).toInstance(new
ServiceImpl<Car>("myapp.domain.Car"));

but now the idea is, given a list of classes in runtime, bind them to
a particular instance... something like:

// along with some reflection or guicy magic

for (Class<?> clazz : getClasses("myapp.domain")) {

TypeLiteral typeLiteral = new TypeLiteral<Service<Car>>() {};
ServiceImpl service = new ServiceImpl(clazz.getName()); // add types
(...)
bind(typeLiteral).toInstance(service);

}

in order to do the following in client code:

@Inject
Service<SomeDomainClass> service;

does guice provide an equivalent way to accomplish this? i'm also
asking here because lots of features have been added after 1.0. other
ideas on how would you do this? maybe dead simple with standard
reflection?

thanks!

francisco

francisco treacy

unread,
Aug 20, 2008, 3:27:42 PM8/20/08
to google...@googlegroups.com
ok i'm simplifying my question:

how can i bind a generic type to a specific implementation, if i the
only information i have is a Class clazz?

bind(new TypeLiteral<Service< (put type here from clazz) >>()
{}).toInstance(someInstance); // you see here what i'd like to do

as i don't think this is remotely possible, i modified by reflection
the TypeLiteral's "type" actualTypeArguments. when i debug my
injector, i see the Key of the my binding is correctly set to my
clazz. but when i actually @Inject, guice says it can't find the
binding to that type. apart from the actualTypeArguments, do i need to
change something else? or there's no other way than explicitly declare
the binding like so: bind(new TypeLiteral<Service<Car>>() {})... ?

sorry if it was a noob question on generics basics. i'd be glad to get
any additional pointers if you have.

francisco

tzwoenn

unread,
Aug 21, 2008, 8:43:25 AM8/21/08
to google-guice
Using upcoming Guice 2.0's com.google.inject.util.Types this one might
work for you:

for (Class<?> clazz : getClasses("myapp.domain"))
{
// explicitly without wildcard type, because otherwise you can
not bind an instance to that wildcard
TypeLiteral literal =
TypeLiteral.get(Types.newParameterizedType(Service.class, clazz));
Service service = new ServiceImpl(clazz);
bind(literal).toInstance(service);
}

BR, Sven


On Aug 20, 9:27 pm, "francisco treacy" <francisco.tre...@gmail.com>
wrote:
> ok i'm simplifying my question:
>
> how can i bind a generic type to a specific implementation, if i the
> only information i have is a Class clazz?
>
> bind(new TypeLiteral<Service< (put type here from clazz) >>()
> {}).toInstance(someInstance); // you see here what i'd like to do
>
> as i don't think this is remotely possible, i modified by reflection
> the TypeLiteral's "type" actualTypeArguments. when i debug my
> injector, i see the Key of the my binding is correctly set to my
> clazz. but when i actually @Inject, guice says it can't find the
> binding to that type. apart from the actualTypeArguments, do i need to
> change something else? or there's no other way than explicitly declare
> the binding like so: bind(new TypeLiteral<Service<Car>>() {})... ?
>
> sorry if it was a noob question on generics basics. i'd be glad to get
> any additional pointers if you have.
>
> francisco
>
> On Wed, Aug 20, 2008 at 4:39 PM, francisco treacy
>

francisco treacy

unread,
Aug 21, 2008, 9:47:02 AM8/21/08
to google...@googlegroups.com
thanks sven.

i finally found a better way to accomplish this without guice.

as i'm also using salve (http://code.google.com/p/salve), i created a
CustomLocator where i can manage salve.Keys and return appropriate
bindings as i want, even before guice is aware of all that. basically
i had to implement the Locator interface:

public Object locate(Key key) {
if (key.getType() == Repository.class) {
Type type = key.getGenericType();
// get the "actualTypeArgument" Class clazz
return new RepositoryImpl(clazz);
}
return null;
}

...and declare GuiceLocator after my own one.

francisco

Simone Tripodi

unread,
Oct 3, 2008, 2:57:51 AM10/3/08
to google...@googlegroups.com
Hi Guys,
I know the thread is a little old and you've already found a solution,
but this week I had to face the same problem and I'm writing you just
to tell how I resolved my issue and share the idea:

my application is "profiled" for different environment, it means that
a specific interface, in stage environment, is implemented by a
specific class, that is really different from the production
implementation; so, using the apache's commons-discovery

http://commons.apache.org/discovery/

my binding module implementation is

public void configure(Binder binder) {
...
DiscoverClass discover = new DiscoverClass();
binder.bind(MyInterface.class).to(discover.find(MyInterface.class));
...
}

It's currently working in a production environment without any problem.
Best regards,
Simone

2008/8/21 francisco treacy <francisc...@gmail.com>:

--
My LinkedIn profile: http://www.linkedin.com/in/simonetripodi
My GoogleCode profile: http://code.google.com/u/simone.tripodi/
My Picasa: http://picasaweb.google.com/simone.tripodi/
My Tube: http://www.youtube.com/user/stripodi
My Del.icio.us: http://del.icio.us/simone.tripodi

Anthony MULLER

unread,
Oct 7, 2008, 8:30:49 AM10/7/08
to google...@googlegroups.com
Thanks for the feedback and link.

Anthony

2008/10/3 Simone Tripodi <simone....@gmail.com>
Reply all
Reply to author
Forward
0 new messages