a guest Mar 20th, 2019 61 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # Scoping containers: context switching
  3. For Yii3 we have been working to split the framework up into different parts that can be used separately.
  4. One of the parts I've been working on a lot is the DI implementation. Traditionally Yii uses arrays for configuration, often these arrays are defined in multiple files and recursively merged to obtain the final configuration.
  5. The goal of this DI implementation is to use DI containers to configure different parts of an application differently.
  7. ## Injecting the DI container
  8. One of the first things they tell you about DI is that if you're injecting a container you're doing it wrong. While this is a good rule to live by, exceptions exist. Specifically parts of your application that decide the execution path will often use a DI container as a service locator to instantiate the request handler and inject its dependencies.
  10. In Yii this routing happens in modules. A module parses a request and routes it to an action. This action has dependencies which are injected by the DI container.
  12. ## Configuration
  13. Configuration of an application happens at different levels. A generic logging service might be configured at the application level while some modules have a different configuration for logging.
  15. Configuration the module specific logging service should never leak out; module A should never get a service meant for module B from the DI container.
  17. Several methods could be used to implement this requirement:
  18. 1. Copy the DI container for each module, then override the module specific entries before passing the container to the module.
  19. 2. Have a module temporarily override the entries in a container using local configuration
  20. 3. Use contextual DI containers
  22. ### Copying the container
  23. Copying the container might seem simple at first, but quickly becomes very complex.
  24. Copying a container means configuration changes no longer propagate in any direction. What should happen to references to already instantiated services? How can we reuse services that are requested from both containers?
  26. ### Temporary overrides
  27. In a system that only has linear execution this could work. It stops working however as soon as we switch from one module to another during a request; it then becomes very hard to keep the DI container in the right state without closely coupling all our code to the DI implementation.
  29. ### Context switching
  30. A solution I have created uses context switching as a solution to the problem of local configuration without introducing significant overhead or the issues mentioned with the other solutions.
  32. The idea is simple: we start with a simple composite container. This container contains no definitions but uses a set of other containers (that must support delegate lookup) to get services.
  33. When registering a DI container with the main container we add a context parameter.
  34. The main container has extra functions for retrieving a service from a specific context only.
  35. Since we want DI and not SL the above functionality is of course not enough; so we add a few more methods to the DI container.
  36. The root container can create containers that are locked to a specific context. These contextual containers could the be injected into a module which uses it just like it would use any other container.
  37. Important fact is that the modules just get a container injected as their dependency without having to know about its context or in which context it operates.
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand