New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support mixed injection and manual wiring #231

Closed
gissuebot opened this Issue Jul 7, 2014 · 11 comments

Comments

Projects
None yet
1 participant
@gissuebot

gissuebot commented Jul 7, 2014

From crazyboblee on August 06, 2008 20:57:09

There are cases where you want most members injected in a given class and
then to do some manual wiring (you may have a couple different bindings
that are wired slightly differently). Right now, it's an all or nothing
proposition.

For a class FooImpl, I should be able to bind a provider to FooImpl, and in
the provider, I should be able to get an injected instance of FooImpl that
I can further work on and return.

Original issue: http://code.google.com/p/google-guice/issues/detail?id=231

@gissuebot

This comment has been minimized.

gissuebot commented Jul 7, 2014

From limpbizkit on August 07, 2008 18:44:10

We discussed this today, and our best idea is to have an @New annotation (not a binding annotation) for provider
methods, plus a toConstant() bind target.

@gissuebot

This comment has been minimized.

gissuebot commented Jul 7, 2014

From limpbizkit on August 07, 2008 18:46:01

I mistyped: I meant a toConstructor() bind target.

@gissuebot

This comment has been minimized.

gissuebot commented Jul 7, 2014

From sven.linstaedt on August 08, 2008 08:06:51

Just for clarification: Are you discussing

  1. a kind of post construction hook (which was also discussed in other issues and
    could be realized using scopes),
  2. a solution for the so called robot-leg problem, that only needs one injector
    (parent injector concept comes along with the "one injector per leg"-problem)
  3. or something completely different?
@gissuebot

This comment has been minimized.

gissuebot commented Jul 7, 2014

From limpbizkit on November 28, 2008 11:30:35

Plan:
We'll Introduce a special binding annotation called '@New'. It is an error to bind to @New by hand; ie. it's an
error to do this:
  bind(Foo.class).annotatedWith(New.class).to(...)
When an injection point asks for an @New Foo, we create a default binding for the constructor of Foo. Foo
must always be a concrete class with a Guice-invokable constructor (ie. @Inject or public no-args).

Complications:
What happens if Foo.class is annotated @Singleton? Do I get the same instance each time I inject @New Foo?
Or different ones?
Suppose I inject both Foo and @New Foo. If Foo.class is annotaed @Singleton, do I get the same instance?

SPI Considerations:
I'm tempted to make it so @New is 1:1 with constructor bindings. For example, given this code:
   bind(Bar.class).to(BarImpl.class);
Guice would create 3 bindings:
   Bar.class linked to BarImpl.class (explicit)
   BarImpl.class linked to @New BarImpl.class (default)
   @New BarImpl to its own constructor (built-in)

Syntactic Sugar:
We confound linked bindings and constructor bindings in the current Guice. It means you can't solve the
turkey bacon problem [ http://tinyurl.com/turkeybaconproblem ]. So I'd like to introduce some syntactic sugar
related to @New:
  bind(Bar.class).toConstructor(BarImpl.class);
     is syntactic sugar for:
  bind(Bar.class).to(Key.get(BarImpl.class, New.class));

@gissuebot

This comment has been minimized.

gissuebot commented Jul 7, 2014

From limpbizkit on December 24, 2008 20:30:47

Deferred to the next release so we can work out the scoping issues.

Labels: -Milestone-Release2.0

@gissuebot

This comment has been minimized.

gissuebot commented Jul 7, 2014

From limpbizkit on June 21, 2009 11:21:49

We've implemented toConstructor() bindings:
  bind(Foo.class).toConstructor(Foo.class.getConstructor(Bar.class, Baz.class));

It's possible to easily implement @New as a simple built-in JIT binding on top of the toConstructor support.

@gissuebot

This comment has been minimized.

gissuebot commented Jul 7, 2014

From sberlin on May 23, 2010 05:26:03

Issue 485 has been merged into this issue.

@gissuebot

This comment has been minimized.

gissuebot commented Jul 7, 2014

From sberlin on May 23, 2010 07:21:19

toConstructor itself solves the TurkeyBacon problem as described @ http://tinyurl.com/turkeybaconproblem .  It would be solved by doing:

public class BritishModule extends AbstractModule {
  public void configure() {
    bind(Bacon.class).to(UncookedBacon.class);
    bind(Bacon.class).annotatedWith(Names.named("Turkey").to(TurkeyBacon.class);
   
bind(Bacon.class).annotatedWith(Names.named("Cooked")).toConstructor((Constructor)InjectionPoint.forConstructorOf(Bacon.class).getMember());
  }
}

.. a little bit unwieldy code-wise, but it works.

Is @New still needed?  It can be worked around pretty easily by:
 
bind(Bar.class).annotatedWith(named("new")).toConstructor((Constructor)InjectionPoint.forConstructorOf(BarImpl.class).getMember());
and later using it was @Inject Baz(@Named("new") Bar bar) { ... }

In other words, instead of toConstructor being syntactic sugar for @New, @New would
be syntactic sugar for toConstructor.

It'd be pretty easy to hack up, either way.

@gissuebot

This comment has been minimized.

gissuebot commented Jul 7, 2014

From sberlin on May 23, 2010 07:32:01

FYI - I committed a test in r1166 that asserts that toConstructor solves the
turkeybacon problem.

@gissuebot

This comment has been minimized.

gissuebot commented Jul 7, 2014

From sberlin on May 23, 2010 08:18:54

Thinking about this some more... it looks like attempts to introduce @New would
introduce a lot confusion.  For example, if Bar is linked to BarImpl.class, what
would "@New Bar" return?  What if Bar was linked to Provider<Bar>, or @Provides Bar.
 Would @New just be disallowed on interfaces because of that confusion?  

I think we're safest adding an easy-to-use "find the right constuctor" method,
something like <T> Constructor<T> Constructors.forConstructorOf(Class<T> clazz), to
reduce the boilerplate from comment #8 of using InjectionPoint to find the right
constructor.  Then users can use it to create their own "new" bindings, annotated
with whatever they'd like.  That way, things like "@New Bar" would be defined,
because the user would have had to define it.

I'm for closing this as "will not fix" -- please chime in if you think otherwise!

@gissuebot

This comment has been minimized.

gissuebot commented Jul 7, 2014

From sberlin on October 24, 2010 17:15:54

Closing as fixed because toConstructor allows this with some configuration (bind your object with toConstructor and a custom @New annotation).

Status: Fixed

@gissuebot gissuebot closed this Jul 7, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment