Cool! Thanks for sharing back your success! I'm glad I was able to help you.
I agree that option #3 couples the container and the instance. However this
is slightly easy to get around if you introduce one layer of
abstractedness. Let me give you a concrete example.
Imagine you have a base module:
abstract class GenericInterface<T> {
private final Class<T> myClass;
public GenericInterface(Class<T> myClass) {
this.myClass = myClass;
}
@Inject
private registerThis(GenericRegistry registry) {
registry.register(myClass, this);
}
}
class GenericRegistry {
private final HashMap<Class<?>, GenericInterface<?>> map = new HashMap<>();
// Package private may be preferred.
public <T> void register(Class<T> cls, GenericInterface<T> impl) {
// Error handle prior mapping. (also ignore warnings)
map.put(cls, impl);
}
public <T> GenericInterface<T> getImpl(Class<T> cls) {
return (GenericInterface<T>)map.get(cls);
}
// or get an iterator of all GenericInterfaces... or any other
kind of API that makes sense for your situation
}
Then you have another module the depends only on the base and you inject
the registry there:
class API {
@Inject
public API(GenericRegistry registry) { ... }
// ...
}
And your implementations can come from any module that depends on the base
(consider the potential of having guice modules that extend your
application):
class A extends GenericInterface<SomeClass> { ... }
class B extends GenericInterface<SomeClass'> { ... }
Hope that helps you see how you can decouple the coupling =). You need to
be aware that you can't use the Registry until the entire injector is
created. If you use it in any constructor or injection method then it may
not have finished registering all bindings. This is a problem I solve by
introducing start/stop methods on all services -- it's a good practice
anyways since the injector is even faster to construct (to find errors
before any initialization occurs).
Nate
On Wed Feb 11 2015 at 3:41:55 PM Karsten Schulz <
[email protected]> wrote:
> Hello,
>
> ok i have try this and thanks a lot. it's work very well. my solutions is
> a combine from multibindings and the the single add method. I use
> multibinding and inject the collection to the class and iterate over this
> and call for every single element the add method. your third option works
> also very well. in the first phase i have implement this on this way. but
> in my opinion the uncouple class design will be broken, because the bean
> class have to be know about the register class. but i understand the
> feature, that the automaticly add, maybe in scala is this possibility very
> well, but i think it's a little bit bad small, cause the strict couple
> between bean and register.
>
> Am Dienstag, 10. Februar 2015 21:16:18 UTC+1 schrieb Nate Bauernfeind:
>>
>> Couple of comments.
>>
>> 1. Resolving generic type dependencies can be done without named
>> annotations. The trick is to use a Guice TypeLiteral. See:
>> http://google.github.io/guice/api-docs/latest/javadoc/
>> index.html?com/google/inject/TypeLiteral.html
>>
>> Your bind becomes something more like:
>> bind(new TypeLiteral<GenericInterface<String>>() {}).toInstance(new
>> GenericClass<String>());
>>
>> 2. You probably want to use the multibinder extension to inject all
>> implementations into a single location. See: https://github.com/
>> google/guice/wiki/Multibindings
>>
>> Your binding becomes more like:
>> Multibinder<GenericInterface> mBinder = Multibinder.newSetBinder(binder(),
>> GenericInterface.class);
>> mBinder.addBinding().toInstance(new GenericClass<String>());
>>
>> 3. Instead of using multibinder you might enjoy something of an
>> auto-registration approach.
>>
>> public abstract class BaseGenericInterface<T> extends GenericInterface<T>
>> {
>> @Inject
>> public void registerThis(GenericInterfaceRegistry registry) {
>> registry.registerThis(this);
>> }
>> }
>>
>> I like this approach the most because in Scala I can actually put the
>> method (and implementation) in the interface and it just automagically
>> happens. (When I do this, I also almost always pass a scala
>> manifest/typetag to the registry too.)
>>
>> Happy guicing!
>> Nate
>>
>> On Tue Feb 10 2015 at 2:47:11 PM Karsten Schulz <[email protected]>
>> wrote:
>>
> Hello guys,
>>>
>>> i have a handling question about guice. i like really dependency
>>> injection and use this in the most of private projects. But currently i
>>> have some problems with generics and multiple binding for one interface.
>>> For the first problem i have another solution. i don't know if thats works,
>>> but i will test it in the future.
>>>
>>> So the second problem is for me currently a little bit difficult to
>>> understand.
>>>
>>> The starting point is:
>>>
>>> I have an Interface thats supports Generic, for Example:
>>> public interface GenericInterface<T> {}
>>>
>>> So i have also an implemented class, for Example:
>>> public class GenericClass<T> implements GenericInterface<T> {}
>>>
>>> So this interface and class have some generic methods.
>>>
>>> In my Modul i define some bindings:
>>>
>>> public class ExampleModule extends AbstractModule {
>>>
>>> public void configure() {
>>> bind(GenericInterface.class).annotatedWith(Names.named("Example"
>>> )).toInstance(new GenericClass<String>());
>>> bind(GenericInterface.class).annotatedWith(Names.named("Second"
>>> )).toInstance(new GenericClass<Integer>());
>>> }
>>> }
>>>
>>> Now my Question. In my opinion, i have to different instances from
>>> GenericInterface. So i can inject this with the annotation @Named
>>>
>>> But in another case, i have a class, that will add all implementations
>>> of GenericInterface without specify the name.
>>>
>>> public class ExmapleClass {
>>>
>>> @Inject
>>> public <T> void addGeneric(GenericInterface<T> genericInterface) {}
>>> }
>>>
>>> Ok first, i find out, that generic methods doesn't work, but it's also
>>> not possible to add automaticly all GenericInterfaces to this method. So i
>>> searching for an solutions, that has the feature like the ServiceTracker
>>> functionality from OSGi.
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "google-guice" group.
>>>
>> To unsubscribe from this group and stop receiving emails from it, send an
>>> email to [email protected].
>>> To post to this group, send email to [email protected].
>>
>>
>>> Visit this group at http://groups.google.com/group/google-guice.
>>> To view this discussion on the web visit https://groups.google.com/d/
>>> msgid/google-guice/293f68ba-b645-493d-9dcb-1f6165564e2f%
>>> 40googlegroups.com
>>> <https://groups.google.com/d/msgid/google-guice/293f68ba-b645-493d-9dcb-1f6165564e2f%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>> --
> You received this message because you are subscribed to the Google Groups
> "google-guice" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/google-guice.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/google-guice/e5e5f2be-d414-4f44-9980-bbb3280eeeaa%40googlegroups.com
> <https://groups.google.com/d/msgid/google-guice/e5e5f2be-d414-4f44-9980-bbb3280eeeaa%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>
--
You received this message because you are subscribed to the Google Groups
"google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/google-guice.
To view this discussion on the web visit
https://groups.google.com/d/msgid/google-guice/CAHNex9-uo_K4RxJQybETmWbM%3DCYmi-q1S4sUvYpzyKdYTbpsKw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.