Russ, I appreciate you taking the time to respond. Unfortunately I'm afraid I don't understand enough about using child injectors to make your suggestion work, though I did try.
Ultimately my implementation above fails because I don't have a way to tell the factory generated by FactoryProvider.newFactory() to use the CImpl implementation for C without explicitly creating that binding. But creating that binding exposes a new problem, because Guice doesn't know how to inject an @Assisted annotated value outside of the assistinject framework, as detailed in the response to this stackoverflow post: http://stackoverflow.com/questions/1595723/how-to-bind-assisted-injected-class-to-interface The simplest solution for me at this point is to (sadly) abandon Guice for the creation of this object. I can do the following and make it work: class CFactory { public C create( D d ) { return new CImpl( d ); } } class B { @Inject CFactory cFac; void executeB( D d ) { cFac.create( d ).executeC(); } } In this approach, CImpl is completely outside Guice's control, but it allows me to pass in my runtime D implementation without confusing Guice. Not my first choice, but I thank everyone for the suggestions. If anyone has further thoughts, feel free to share. Thanks, Ryan On Dec 9, 9:20 am, Russ Milliken <[email protected]> wrote: > One other option is the use of a child injector, rather than a custom > scope. I'm sorry that I don't have time to elaborate but perhaps someone > else on this list could. > > Basically, in the place where you need the custom (or different) binding you > could create a child injector from the main one, overriding the default > binding in a custom module and passing this to the child injector via > Modules.override(). > > -Russ > > > > > > > > On Thu, Dec 9, 2010 at 9:40 AM, Ryan <[email protected]> wrote: > > Fred, > > > Thank you for the prompt response! I spent some time last night > > playing with your suggestion, and I was able to get it to work. > > However, I was hoping to find a solution that didn't require the extra > > work of a custom scope, with the intrusion of the framework into my > > domain code. This is not a webapp, and using RequestScoped doesn't > > really make sense in this context either. > > > I'm wondering if there's a possible solution that could be confined to > > annotations and the Provider interface alone, with the rest of the > > configuration in modules. Am I barking up the wrong tree? > > > Thanks, > > Ryan > > > On Dec 8, 5:49 pm, Fred Faber <[email protected]> wrote: > > > When I hear that a dependency depends on a runtime value I immediately > > think > > > about binding the value in scope. You can then manually seed the value > > > upstream before you traverse the downstream call graph. > > > > Something like: > > > > D d = getD(); > > > simpleScope.seed(D.class, d); > > > doSomethingThatRequiresD(); > > > > ... > > > > class DependsOnD { > > > // Inject a provider this class is created before D is in scope > > > @Inject Provider<D> dProvider; > > > ... > > > void useD() { > > > dProvider.get().doSomething(); > > > } > > > > } > > > > ... > > > > // Or you might have your own scope > > > bind(D.class).in(RequestScoped.class); > > > > -Fred > > > > On Wed, Dec 8, 2010 at 7:42 PM, Ryan <[email protected]> wrote: > > > > Hello everyone, > > > > > Been an avid user of Guice for a while now, and just ran across a new > > > > situation that has me stumped. I've got a dependency that I need to > > > > be able to change at runtime. The catch is, the piece of code that > > > > needs it is far down the call graph from where it changes. I've > > > > attempted to use assisted inject to let me customize the object at > > > > runtime, but there's a hitch. > > > > > An example will make this more clear: > > > > > class MyModule extends AbstractModule { > > > > protected void configure() { > > > > > bind( BFactory.class ).toProvider( FactoryProvider.newFactory( > > > > BFactory.class, > > > > B.class ) ); > > > > } > > > > } > > > > > interface BFactory { > > > > B create( D d ); > > > > } > > > > > class A { > > > > �...@inject BFactory bFac; > > > > > void executeA( D d ) { > > > > bFac.create( d ).executeB(); > > > > } > > > > } > > > > > class B { > > > > �...@inject C c; > > > > > void executeB() { > > > > c.executeC(); > > > > } > > > > } > > > > > class C { > > > > �...@inject @Assisted D d; > > > > > public void executeC() { > > > > System.out.println( d ); > > > > } > > > > } > > > > > class D {}; > > > > > Now I can call A.executeA() with different instances of D (which is > > > > needed by C) at runtime. Executing the above classes with the > > > > following code,two different D objects are written to stdout as > > > > expected: > > > > > A a = i.getInstance( A.class ); > > > > a.executeA( new D() ); > > > > a.executeA( new D() ); > > > > > This works as long as I only create C through the BFactory, and as > > > > long as everything is concrete. But if I introduce an interface, > > > > there's a problem, as follows: > > > > > class MyModule extends AbstractModule { > > > > protected void configure() { > > > > > bind( BFactory.class ).toProvider( FactoryProvider.newFactory( > > > > BFactory.class, > > > > B.class ) ); > > > > bind( C.class ).to( CImpl.class ); > > > > } > > > > } > > > > > interface C { > > > > void executeC(); > > > > } > > > > > class CImpl implements C { > > > > �...@inject @Assisted D d; > > > > > public void executeC() { > > > > System.out.println( d ); > > > > } > > > > } > > > > > This gives me an error: > > > > > 1) No implementation for D annotated with > > > > @com.google.inject.assistedinject.Assisted(value=) was bound. > > > > while locating D annotated with > > > > @com.google.inject.assistedinject.Assisted(value=) > > > > for field at CImpl.d(AssistedInjectTest.java:62) > > > > at MyModule.configure(AssistedInjectTest.java:28) > > > > > The BFactory binding is still okay, but the C->CImpl binding is what > > > > produces the error. I assume this is because class C could > > > > conceivably be wired into another class as a dependency (in addition > > > > to class B) and Guice wouldn't know what to do with the dependency on > > > > D. > > > > > What's the best solution to this? Am I making it needlessly complex? > > > > I need to know if there's a way to supply D to C without B knowing > > > > anything about it, while still allowing A to change what D is. > > > > > Thanks, > > > > Ryan > > > > > -- > > > > 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%2bunsubscr...@google > > > > groups.com> > > <google-guice%2bunsubscr...@google groups.com> > > > > . > > > > 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]<google-guice%2bunsubscr...@google > > groups.com> > > . > > 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.
