On Tue, Jun 8, 2010 at 2:24 AM, Tim Boudreau <[email protected]> wrote:
>
> I am simply suggesting that there should be a way to bind Server ->
> AbstractServer -> ServerImpl -> ServerImplSubclass in a single call.
> Whether it is a singleton or has any scope or is @Named is entirely
> orthagonal.
> //allow @Inject Server | AbstractServer | ServerImpl |
> ServerImplSubclass to succeed w/o explicit bind() calls for each type
>
> bindHierarchy(Server.class).annotatedWith(named("public")).to(ServerImpl.class);
>
I'm not certain scope is fully orthogonal. If ServerImpl is not a singleton
here, the bindHierarchy class can be accomplished by just figuring out the
difference in types between the bindHierarchy(Super) call & the to(Sub)
call, and essentially call bind(SuperN).[annotatedWith(..).].to(Sub) for
every resulting type. But, if you want to bind the classes to a singleton,
those implicit bind calls would be incorrect, because each one would be
binding to a distinct singleton of ServerImpl. To fix that, bindHierarchy
could also do a binding of the to(Sub) call in the wanted scope, but that
would have the side effect of possibly breaking a future caller who wanted
to do something like
'bindHierarchy(Server.class).annotatedWith(named("private")).to(ServerImpl.class)
and want a different ServerImpl instance.
If you're willing to manipulate the resulting binding too -- annotate
ServerImpl's binding with named("public") -- things are a lot safer. Here's
a helper function that can do just that:
<T> bindHierarchy(Class<? extends T> binding, Class<T> topmostParent,
Annotation annotation, Scope scope) {
//pseudocode:
Key bKey = Key.get(binding, annotation);
bind(bKey).in(scope);
for(Class<?> intrface : binding.getInterfaces()) {
bind(intrface).annotatedWith(annotation).to(bKey).in(scope);
}
while(true) {
binding = binding.getSuperclass();
bind(binding).annotatedWith(annotation).to(bKey);
if(binding == topmostParent)
break;
}
}
If you want to be super safe, you can just specify the binding, annotation &
scope, and take the bound types as a vararg or list. I've done exactly that
in the past, when I wanted to bind a ScheduledThreadPoolExecutor instance to
Executor, ExecutorService, ScheduledExecutorService, and some other internal
types.
sam
>
> This is just specifying an array of types to bind to the same
> implementation class, while taking advantage of the fact that
> inheritance dictates the contents of that array, so you can specify
> the entire array simply by indicating the head and tail of it. There
> is no ambiguity since a hypothetical @Inject AbstractServer2 cannot be
> an instance of { Server, AbstractServer, ServerImpl,
> ServerImplSubclass }.
>
> My apologies if my example suggested this had something to do with
> singletons.
>
> The irony of all this being, I generally believe in avoiding deep
> inheritance hierarchies like the plague. However, if you are writing
> something for other people to extend, your audience is most likely
> people who expect to use inheritance and will be baffled otherwise.
>
> -Tim
>
> --
> 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]<google-guice%[email protected]>
> .
> For more options, visit this group at
> http://groups.google.com/group/google-guice?hl=en.
>
>
--
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.