I can't seem to grasp the modules of dagger.
Should I create a new instance of a module each time I want to inject stuff?
Should I create only one instance of a module? If so where should I do it?
Is there a more complex example of fragments and activities used with dagger?
Thanks
You should think more about #Component than #Module. Modules just create objects that need further initialization. The actual work happens in Components, which modules are part of.
Should I create a new instance of a module each time I want to inject stuff?
You should create your module when you create the Component it is part of, since only this component is going to need it. If you find yourself creating the same module multiple times, you are most likely doing something wrong.
A module uses additional arguments (pass them in via the constructor) to create more complex objects. So if you were to have e.g. a UserModule you'd pass in the a user to create user dependent objects from the resulting component. If the user changes lose the old component and create a new module and a new component—the old objects should not be used anymore.
Keep the component where / when appropriate and be sure to use Scopes, since they determine the lifetime of your component.
Should I create only one instance of a module? If so where should I do it?
You most likely will just create a single instance of #Singleton annotated Components and Modules. In android you'd most likely keep the reference to the component (not the module!) in the Application or some real 'singleton'.
Is there a more complex example of fragments and activities used with dagger?
Try googling. There are lots of high quality tutorials with linked github repositories that go into much more depth and detail as would be possible here on SO. e.g. see Tasting dagger 2 on android.
Related
I’m converting a large service to use Dagger, and I have a component with a lot of dependencies in the generated graph, and I want to ensure everything is scoped.
Initially, I tried to look at all the modules of the component to ensure that all their #Provides were annotated with a scope. However, one can have a class that uses #Inject, not have any #Provides methods in the modules, and that be unscoped if not specified on the class.
Right now, in order to check if I missed anything, I go into the generated code and look to see if anything is missing a double-checked locked provider. However, this isn’t very efficient and feels error-prone, as there are cases (such as a component dependency) where we don’t need a provider, since we reference the dependent component directly.
Is there a simple way to check for unscoped bindings for a component? I’d like to make sure that for the component, only one instance of every object in its graph is created in its lifetime.
In an asp.net MVC application, rather than bloating Application_Start() with lots of Autofac scaffolding such as Component registrations, I wish to organise the application by having this is separate files.
Is there an example of a pattern I could follow for this? Is this what an autofac module is for?
For example, if i wanted all of the Widget-related registration in the same file, maybe in the Widget MVC area somewhere:
builder.RegisterType<FooWidget>().As<IWidget>();
builder.RegisterType<BarWidget>().As<IWidget>();
Yes. That is exactly what modules do. Depending on how much you need to register, you could choose to create a module per assembly, module per concept/type (i.e. ControllersModule, RepositoriesModule etc). In your case you might want to have a WidgetsModule. Your Application_Start() will then be nothing more than:
Assembly[] assemblies = BuildManager.GetReferencedAssemblies().OfType<Assembly>().ToArray();
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterAssemblyModules(assemblies);
IContainer container = containerBuilder.Build();
There are a lot of useful methods for registering types. It might minimize the amount of registration code to a point where it is fine to have it in a single place. In your example a RegisterAssemblyTypes(assembly).As<IWidget>() should be enough to register all IWidgets.
If I know I'm going to require a lot of registrations, I start with modules. Other times I start small and put all registrations in one place until the need arises for more readable/maintainable solution and then refactor towards modules.
I used #subcomponent mostly for case activities need to use some shared objects from application component, or fragments components want to use some objects provided by container activity.
Now I am wondering if I can make some activity components be subcomponent of another activity component. For example, the TaskDetailActivity has a task object and want to provide to some other activities such as TaskParticipantActivity, TaskProgressActivity and some fragments.
The traditional way to provide task object to other activities is set it into intent object, but how about if we want to use Dagger2 for this case?
Update: my sistuation similar with the case of UserScope in this article http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/, but instead of saving the user component in Application class, can I save in an activity, i.e TaskDetailActivity?
Components are for grouping objects of a similar lifecycle. While Components may happen to correspond to a particular set of functionality (like a TaskComponent for injecting a TaskActivity and a TaskPresenter) it is not always possible or desirable to insist on only one Component per set of functionality (for instance, insisting on only one TaskComponent for all task related activities and dependencies).
Instead, in Dagger 2 re-usability is available through Modules which you can very easily swap in and out of Components. Within the constraints of the advice for organising your Modules for testability in the Dagger 2 official documentation you are able to organise Modules congruent with your functionality (e.g., a TaskModule for all-task related dependencies). Then, because Components are so lightweight, you can make as many as you like to deal with the different lifecycles of your Activities and so on. Remember also that you can compose Modules using the Class<?> [] includes() method inside the Module #interface.
In your particular scenario, you want to share the Task object from a TaskDetailActivity. If you held a reference to the Task within your TaskDetailActivity then that reference will no longer be available when TaskDetailActivity is destroyed. While you could try some solution of holding binding the Task in a Module and then maintaining a reference to that Module at the app-scope level, you would essentially be doing the same as the UserScope at the app-scoped level in the article you have linked. Any kind of solution for sharing the Task object between Activity using Dagger 2 would necessarily involve maintaining a reference to the object at the app-scoped level.
Using Dagger 2 doesn't mean that the new keyword or serialization/deserialization of Parcelables is now wrong and so if your first intuition is to use Intent to communicate then I would say that you are right. If you need a more robust solution than directly communicating the Task, then you could extract a TaskRepository and transmit an Intent between Activity that contains the id of the Task you wish to retrieve. Indeed, some of the Google Android Architecture Blueprints have a solution just like this.
How can I manipulate other modules without editing them ? very the same thing that wordpress modules do .
They add functionality to core system without changing the core code and they work together like a charm.
I always wanted to know how to implement this in my own modular application
A long time ago I wrote the blog post "Use 3rd party modules in Zend Framework 2" specifically about extending Zend Framework 2 modules. The answer from Bez is technically correct, it could be a bit more specific about the framework.
Read the full post at https://juriansluiman.nl/article/117/use-3rd-party-modules-in-zend-framework-2, but it gives you a clue about:
Changing a route from a module (say, you want to have the url /account/login instead of /user/login)
Overriding a view script, so you can completely modify the page's rendering
Changing a form object, so you could add new form fields or mark some required field as not required anymore.
This is a long topic, but here is a short gist.
Extensibility in Zend Framework 2 heavily relies on the premise that components can be interchanged, added, and/or substituted.
Read up on SOLID principles: http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
Modules typically consists of objects working together as a well-oiled machinery, designed to accomplish one thing or a bunch of related things, whatever that may be. These objects are called services, and managed by the service locator/service manager.
A big part of making your module truly extensible is to expect your developers to extend a class or implement a certain interface, which the developer register as services. You should provide a mode of definition wherein the developers can specify which things he wants to substitute, and/or add their own services to -- and this is where the application configuration comes in.
Given the application configuration, you should construct your machinery a.k.a. module services according to options the developer has specified i.e., use the developer defined Foo\Bar\UserService service as the YourModule\UserServiceInterface within your module, etc. (This is usually delegated to service factories, which has the opportunity to read the application configuration, and constructs the appropriate object given a particular set of configuration values.)
EDIT:
To add, a lot can be accomplished by leveraging Zend's Zend\EventManager component. This allows you to give developers the freedom to hook and listen to certain operations of your module and act accordingly (See: http://en.wikipedia.org/wiki/Observer_pattern)
I have a service IService that several components depend on. The components come and go depending on user actions.
It so happens that the implementation of IService is expensive, and I want 1 instance shared across all components. So far so good, I can use:
builder.RegisterType<ExpensiveStuff>().As<IService>().SingleInstance();
However, I don't want to ExpensiveStuff to live forever once built; I only want it to exist when one or more components holds a reference to it.
Is there a built in means of achieving this in Autofac?
I think you'll have to make sure that your usage of those dependencies happen within an instance scope.
The Orchard project could be a source of inspiration here. They use a set of scopes for Unit of Work; see the ShellContainerFactory.cs source file.