shiroyuki / Imagination

Java Beans-inspired Dependency Injection Framework for Python
https://imagination.readthedocs.io/en/latest/
4 stars 2 forks source link

Automatically wire entity together like Java Bean #20

Closed shiroyuki closed 4 years ago

shiroyuki commented 8 years ago

On instantiation, each entity should be able to automatically figure out any parameters not explicitly defined in the configuration and wire it to the constructor. For instance, given the following classes,

class Logger(object):
    # ... omitted the whole class

class Service(object):
    def __init__(self, name, logger):
        self.name   = name
        self.logger = logger
    # ... omitted the rest

in version 1.x, we have to define the configuration like this:

<imagination>
  <entity id="logger" class="Logger"/>
  <entity id="service" class="Service">
    <param type="str" name="name">app</param>
    <param type="entity" name="logger">logger</param>
  </entity>
</imagination>

in version 2.x, as long as there exists an entity where the ID or type is the same as the one of an undefined parameter, that entity will be wired to the respective undefined parameter.

<imagination>
  <entity id="logger" class="Logger"/>
  <entity id="service" class="Service">
    <param type="str" name="name">app</param>
    <!-- "logger" is omitted but eventually wired with ID-based auto-wiring -->
  </entity>
</imagination>

Note that the type-based auto-wiring requires at least Python 3.5 or any version/implement of Python language that supports PEP 484.

Readings

shiroyuki commented 5 years ago

The actual implementation is actually simpler than originally anticipated with the combination of the standalone mode and #33 (service decorator).

How it works

First, auto-wiring is enabled by default. Only in the standalone mode (v3), you can turn it off by setting auto_wired to False. For example,

@service(auto_wired=False)
class Foo:  # ...

Also, it heavily relies on the annotation of the parameters.

@service(auto_wired=True)
class Foo:
    def __init__(self, bar:Bar):  # ← This will make Imagination search for Bar
        # ...

Theoretically, unlike Spring Beans, Imagination doesn't require component scanning as by the time that dependency class is imported, the class is automatically registered.

shiroyuki commented 5 years ago

After a few considerations, the current (at the time of writing) implementation is pretty much straight forward. This implies that auto-wiring only attempts to wire a service specified in the type hints / parameter annotation.

TODOs:

shiroyuki commented 4 years ago

This duplicates #33 .