google-code-export / google-guice

Automatically exported from code.google.com/p/google-guice
Apache License 2.0
2 stars 1 forks source link

Keyed providers #211

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I was thinking about how something like conversation scope would work with
partial injection, and came up with this example showing how a User scope
could work:

configure() {
  bind(UserPrefs.class).withKey(UserKey.class).toKeyedProvider(...)
}

class UserSpecificView {
  @Inject
  UserPrefs prefs;
  ...
}

class ViewUsingClass {
  @Inject
  KeyedProvider<UserKey, UserSpecificView> viewSource;

  void handleRequest(UserKey userKey) {
    UserSpecificView view = viewSource.get(userKey);
  }
}

The basic idea is that Guice should allow modules to bind providers that
add another dimension in the injector map.  Guice would need to get
involved because the module implements a provider from UserKey to
UserPrefs, but the ViewUsingClass wants a provider from UserKey to
UserSpecificView.  Guice would automatically create the intermediate provider.

Compared to something like request scope, I think this is actually
preferable because you can tell from handleRequest that it is called from
*outside* User scope but can create objects that are *inside* User scope,
because it takes UserKey as an argument.  Only instances that are created
inside User scope could have a zero-argument handleRequest() method,
because they can have the UserKey (or any other UserKey-scope class)
injected into them.

To my way of thinking, this is better than a thread-local because it
clearly distinguishes methods that run inside versus outside a scope.  For
methods that run outside a scope, it also allows you to control which scope
is used by passing a different key.

Original issue reported on code.google.com by bslesinsky on 18 Jun 2008 at 11:56

GoogleCodeExporter commented 9 years ago
I'd like to build this as part of "assistedinject++". Here's a sketch of the 
API in case you're curious:

The user specifies any factory interface:
  interface ViewSource {
    UserSpecificView create(User user);
  }

In their Injector, they bind User.class to a special target. Not sure the 
correct words, but the idea is generally 
something like this:
  bind(User.class).asCreateTimeParameter();

and they bind the factory, just like in AssistedInject:
  bind(ViewSource.class).toProvider(FactoryProvider.factoryFor(RealUserSpecificView.class));

But unlike assistedinject, the User parameter can be injected anywhere: In the 
returned RealUserSpecificView 
class, in its dependencies, or even as a Provider within its dependencies. 
Behind-the-scenes this will create a 
child injector that has a proper binding for User.class. It will fulfill the 
ViewSource injection using that 
injector.

Original comment by limpbizkit on 19 Jun 2008 at 9:05

GoogleCodeExporter commented 9 years ago

Original comment by cgruber@google.com on 16 Jul 2012 at 6:15

GoogleCodeExporter commented 9 years ago

Original comment by cgruber@google.com on 18 Nov 2013 at 8:05