Pyjection is a lightweight python dependency injection library
The most important class is DependencyInjector
which lets us register classes and retrieve instances.
from pyjection.dependency_injector import DependencyInjector
class OuterClass(object):
def __init__(self, inner_class):
self.inner_class = inner_class
class InnerClass(object):
def __init__(self):
self.foo = "bar"
container = DependencyInjector()
container.register(InnerClass)
container.register(OuterClass)
outer = container.get("outer_class")
print(outer.inner_class.foo) # Will print "bar"
When no id is specified in the register
method Pyjection creates implicit bindings for classes.
The implicit bindings assume your code follows PEP8 conventions: your classes are named in CamelCase
,
and your args are named in lower_with_underscores
. Pyjection transforms
class names to injectable arg names by lowercasing words and connecting them
with underscores.
Class name | Arg name |
---|---|
Foo |
foo |
FooBar |
foo_bar |
It is also possible to manually set the id of a class when during its registration by specifying it as a second arguments.
container.register(FooClass, "inner_class")
With the example above, FooClass
will later be injected to arguments named inner_class
To retrieve an instance of a class from the dependency injector 2 options are available in the get
method:
- Specify the
lower_with_underscores
name of the class as a string - Give the class as parameter
from pyjection.dependency_injector import DependencyInjector
class FooClass(object):
pass
container = DependencyInjector()
container.register(FooClass)
container.get("foo_class")
# Same as
container.get(FooClass)
The dependency injector lets us register a singleton. To register a singleton the method register_singleton may be used. It takes the same arguments as register.
from pyjection.dependency_injector import DependencyInjector
class SingletonClass(object):
pass
container = DependencyInjector()
container.register_singleton(SingletonClass)
# Or we could specify an id
container.register_singleton(SingletonClass, "other_id")
class_1 = container.get("other_id")
class_2 = container.get("other_id")
print(class_1 is class_2) # True
Sometimes the argument we need to inject is not an instance of a class.
The register
and register_singleton
methods return a service object that lets us specify what we want to bind to a given argument by using the add_argument
method.
from pyjection.dependency_injector import DependencyInjector
class FooClass(object):
def __init__(self, foo):
self.foo = foo
container = DependencyInjector()
service = container.register(FooClass)
service.add_argument("foo", "bar")
foo_class = container.get("foo_class")
print(foo_class.foo) # Will print bar
A service argument can also reference another dependency injector service. It is useful when we want to inject a class not matching the argument name.
from pyjection.dependency_injector import DependencyInjector
from pyjection.reference import Reference
class OuterClass(object):
def __init__(self, inner_class):
self.inner_class = inner_class
class FooClass(object):
def __init__(self):
self.foo = "bar"
container = DependencyInjector()
container.register(FooClass)
container.register(OuterClass).add_argument("inner_class", Reference('foo_class'))
instance = container.get(OuterClass)
print(instance.inner_class.foo) # Will print bar