2008/12/23 Luis <[email protected]>:
> From the "philosophic" point of view I think the answer is now clear
> to me. But I am still not sure about how does Guice handle this kind
> of situations:
>
> class MenuTree extends MenuElement {
>   @Inject List<MenuElement> items;
> }
>

There are many ways, you can do it like this:
Implement provider of List<MenuElement>:

public class MainMenuProvider implements Provider<List<MenuElement>> {
    @Override
    public List<MenuElement> get() {
        List<MenuElement> result = new ArrayList....
       result.add(....);
       result.add(....);
       result.add(....);
       return result;
    }
}

This class would be equivalent to the Spring XML file, but it is Java,
so you have all the benefits of working with Java code like type
safety etc... Now, in your application module you can bind that
provider to every List<MenuElement> or only to the lists with special
annotations. This is how you could bind that provider to any list of
menu elements:

bind(new TypeLiteral<List<MenuElement>>() {})
   .toProvider(new MainMenuProvider());

So whenever you use:

@Inject
private List<MenuElement> menuElements;

you will get the array list returned by your custom provider.

Or you can bind it like this:
bind(new TypeLiteral<List<MenuElement>>() {})
   .annotatedWith(Names.named("MainMenu"))
   .toProvider(new MainMenuProvider());

So now, you will get that list only when used @Named annotation:

@Inject @Named("MainMenu")
private List<MenuElements> mainMenuElements

Actually, you can define your own annotation instead of using @Named
with String literal.

Another way to declare such a menu would be to create one instance and
bind instance in module. You can create separate module for that
purpose or add it to your existing module, like this:

List<MainMenu> mainMenu = Collections.unmodifiableList(Arrays.asList(
    A,
    B,
    C));
bind(new TypeLiteral<List<MenuElement>>() {})
   .annotatedWith(Names.named("MainMenu"))
   .toInstance(mainMenu);


I think that using provider is more like "the right way". More than
that, since providers are by default instantiated by Guice, you can
inject into provider whatever you want, so the result of provider can
depend on other managed objects, where as a module is to be provided
to Guice by you, so you would rather not be able to inject things
there...

Which ever path you choose, notice you can separate that custom
providers or modules from your application and pack them as separate
jars. When you do this, you will be able to provide different sets of
menu items in your application depending on which jar you include into
classpath (remember, one provider can extends another one asking its
parent for menu items and adding/removing whatever you want, as all
this is a java code).
So you will not have to recompile entire application. In Spring, you
would replace the XML file to be able to change main menu. In Guice
you just replace jar with your providers.

Regards,
Witold Szczerba

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to