Skip to content
This repository has been archived by the owner on May 27, 2021. It is now read-only.

[Autumn] Dependency injection after ContextInitializer has done its part. #69

Open
metaphore opened this issue Jan 14, 2018 · 6 comments

Comments

@metaphore
Copy link
Contributor

metaphore commented Jan 14, 2018

I have a case where I need to fill VerticalGroup with a complex items and I chose to go with individual controller instance per view item to encapsulate view logic and item model reference within. So this controller class has a lot of similarities with ViewController, like it has number of LML annotations and also should have injected dependencies to system-wide services/components.

I remember the discussion #40 and it gave me a good point to keep Context not disposed in case I will need to obtain any system component in a future. And so I can, by calling Context#getComponent(Class<?>), but I start thinking if there is a way to automate this process. I mean in that fancy elegant way like ContextInitializer#initiateComponents() does to resolve dependencies, but this time on demand for any specific instance with Autumn annotations like @Inject (maybe even for @OnEvent/@OnMessage, but this could lead to memleaks due to an each instance should be unsubscribed manually).

ContextInitializer is fully dedicated to only initialize Context and is not usable after. Feels like if there should be some injector service, then it better be outside of ContextInitializer and available system wide so anyone can utilize dependency injection later.

@czyzby what do you think, is it a good idea or even is it possible to add such utility functionality to the library core?

@metaphore
Copy link
Contributor Author

Well it is possible, no doubts. I just needed to copy most of the code from ContextInitializer to process annotations. Which in fact made me feel that if dep. injection on demand could exist, it's probably not the worst idea to merge it into ContextInitializer code somehow.

@czyzby
Copy link
Owner

czyzby commented Jan 14, 2018

That's what providers are for. Annotate a class with @Provider or implement DependencyProvider directly. Initialize your objects using injected components and then call Context.provide to create a new instance. See provider examples.

@czyzby czyzby added this to the 1.9 milestone Jan 14, 2018
@metaphore
Copy link
Contributor Author

metaphore commented Jan 15, 2018

Thanks for pointing me out, after reading those examples, it seems like I'm still missing some base Autumn architectural concepts. So I see that Provider is a good thing that I've been always ignoring.

Ok, so I should create Provider for my ItemViewController, and then call Context#provide(Class<T>) to obtain a new instance. But still I have to inject all the dependencies manually inside the DependencyProvider#provide(), right? Is there a simple way to obtain a new instance of Component on demand, so I just annotate ItemViewController's fields with Inject and they get resolved automatically?

@czyzby
Copy link
Owner

czyzby commented Jan 15, 2018

No, I don't believe so. Now that I think about it, there should be a @Provided annotation for types, where it automatically registers a provider for you and uses constructor injection to create new objects.

@metaphore
Copy link
Contributor Author

Yeah, it could be a good solution. Feels like it will require some extra logic for Context or those automatically created Providers, because right now there is no code to inject fields except for ContextInitializer.

@czyzby
Copy link
Owner

czyzby commented Jan 15, 2018

Should be very similar to converting current @Provider's methods to provider instances - you'd just invoke constructors instead of methods. See ReflectionDependencyProvider.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants