toothpick icon indicating copy to clipboard operation
toothpick copied to clipboard

Dagger2 MultiBindings

Open adolgiy opened this issue 5 years ago • 14 comments

Would be very happy to have something like Dagger2 MultiBindings in Toothpick! IntoSet/IntoMap sometimes are very useful.

adolgiy avatar Sep 15 '19 23:09 adolgiy

Do you have an example ? One of the goals of the TP is to remain simple so I would say that such a feature won't make it if it's not essential or very important..

On Sun, Sep 15, 2019, 16:12 Aleksey Dolgiy, [email protected] wrote:

Would very happy to have something like Dagger2 MultiBindings in Toothpick! IntoSet/IntoMap sometimes are very useful.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/stephanenicolas/toothpick/issues/368?email_source=notifications&email_token=AAN7PXJUUXIWRDYQJFLA3HTQJ26PFA5CNFSM4IW4JKE2YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4HLOYKHA, or mute the thread https://github.com/notifications/unsubscribe-auth/AAN7PXO44IW4D2NE2C2IPXLQJ26PFANCNFSM4IW4JKEQ .

stephanenicolas avatar Sep 15 '19 23:09 stephanenicolas

Okay, on my current project (yes, I use Dagger2 :( ) we have two use cases, one of them - analytics. Next gist contains pseudo code, that potentially can handle MultiBindings in Toothpick.

https://gist.github.com/adolgiy/ec0cf74e32f25fb35e656e316cd64ac7

adolgiy avatar Sep 16 '19 12:09 adolgiy

  • Also, Dagger2 has no way to handle order of bindings, but sometimes can be very useful,I think.
  • Also, I personally had issue, when I need a way, which instances should contain set. For example, when you have multiple OkHttp clients in application and each of them is required to have different sets of Interceptor, the only way is to provide method and receive concrete implementations (AuthInterceptor, JsonInterceptor, etc) and build named set with them.

Not sure if everything should be handled via DI, but this just my POV. Thanks for attention. :)

adolgiy avatar Sep 16 '19 12:09 adolgiy

We can keep this one open and do some reading to understand it better. ;)

On Mon, Sep 16, 2019, 05:14 Aleksey Dolgiy, [email protected] wrote:

  • Also, Dagger2 has no way to handle order of bindings, but sometimes can be very useful,I think.
  • Also, I personally had issue, when I need a way, which instances should contain set. For example, when you have multiple OkHttp clients in application and each of them is required to have different sets of Interceptor, the only way is to provide method and receive concrete implementations (AuthInterceptor, JsonInterceptor, etc) and build named set with them.

Not sure if everything should be handled via DI, but this just my POV. Thanks for attention. :)

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/stephanenicolas/toothpick/issues/368?email_source=notifications&email_token=AAN7PXJXM5NF2GEPOKO26TDQJ52BXA5CNFSM4IW4JKE2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6Y6BUQ#issuecomment-531751122, or mute the thread https://github.com/notifications/unsubscribe-auth/AAN7PXNRDHV5YMICK4KRZXTQJ52BXANCNFSM4IW4JKEQ .

stephanenicolas avatar Sep 16 '19 12:09 stephanenicolas

Maybe you can help me help you to understand with some questions?

adolgiy avatar Sep 16 '19 14:09 adolgiy

If I understand correctly, the 2 modules will contribute individually to one item in the set, right ? Is.it the main feature you are looking for ?

stephanenicolas avatar Sep 16 '19 14:09 stephanenicolas

Yep, I think something like this, but more agile than in Dagger2

adolgiy avatar Sep 17 '19 11:09 adolgiy

What do you mean by more agile ? Do you have an idea of API in mind ?

stephanenicolas avatar Sep 17 '19 12:09 stephanenicolas

module constructor bindings:

// Sample 1 - Will provide Interceptor1, Interceptor2 and Interceptor9 in Set<Interceptor>
// Maybe it can receive instances from parent scopes 
bindAsSetOf(Interceptor::class).with(Interceptor1::class, Interceptor2::class, Interceptor9::class)

// Sample 2 - Will provide Interceptor1, Interceptor2 and Interceptor9 for LargeNumber-qualified @Inject
// This one looks not clear enough for me, but let it be 
bindAsSetOf(Interceptor::class)
        .with(Interceptor1::class, Interceptor2::class, Interceptor9::class)
        .to(LargeNumberQualifier::class)

// Sample 3 - Will provide only SmallNumber-qualified interceptors
bindAsSetOf(Interceptor::class).named(SmallNumberQualifier::class)

// Sample 4 - Will provide all interceptors with given annotations
bindAsSetOf(Interceptor::class).named(SmallNumberQualifier::class, LargeNumberQualifier::class)

and constructor-based injects

class SetReceiver @Inject constructor(@SmallNumberQualifier set: Set<Interceptors>)

and it will be cool to have annotation-based way of bindings

// Will be injected in SetReceiver from previous block
@IntoSetOf(type = Interceptor::class, qualifiers = [SmallNumberQualifier::class])
class Interceptor2 : Interceptor

// Will be injected in both SmallNumber-qualified and LargeNumber-qualified sets
@IntoSetOf(type = Interceptor::class, qualifiers = [SmallNumberQualifier::class, LargeNumberQualifier::class])
class Interceptor5 : Interceptor

adolgiy avatar Sep 17 '19 20:09 adolgiy

The gist above was more or less clear. However, the last comment with the proposed API seems somehow complicated.

What's the difference between with and to?

dlemures avatar Sep 18 '19 14:09 dlemures

No meaningful difference there. Just out-of-head thoughts on how API could look like. Little bit chaotic, sorry for that.

adolgiy avatar Sep 18 '19 17:09 adolgiy

No worries, thx for the examples!

We are looking at ways of implementing it :)

dlemures avatar Sep 22 '19 18:09 dlemures

I would also love to suggest a workaround with the current TP APIs. It's clearly something that TP can already accomodate.

I would like to see how complex it is for users to achieve it before considering changing the API itself. The feature is quite specific and it will add complexity. Not sure if the complexity is worth the actual time saved for users.

On Sun, Sep 22, 2019, 11:02 Daniel Molinero, [email protected] wrote:

No worries, thx for the examples!

We are looking at ways of implementing it :)

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/stephanenicolas/toothpick/issues/368?email_source=notifications&email_token=AAN7PXP7NDAHEMACSX7TYD3QK6XM3A5CNFSM4IW4JKE2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD7JLTCI#issuecomment-533903753, or mute the thread https://github.com/notifications/unsubscribe-auth/AAN7PXLPQXW7DCTSTS2MEIDQK6XM3ANCNFSM4IW4JKEQ .

stephanenicolas avatar Sep 22 '19 18:09 stephanenicolas

It is very useful to bind some complex classes into one set, and inject the set into some class and work with them. For example, I have several Ads networks with the same interface. Also, I have a class where I inject Set<AdsInterface> and collect some common data from it. Then, if I need to remove some Ads network, I just remove provide method of specific network and that's all.

morder avatar Dec 11 '19 10:12 morder