Closed Saabertooth closed 5 years ago
Hi!
Could you post some code how you intend to override bindings? Thanks.
But for now, I do not think overriding is good. Inject has one global injector. It means that with overriding in a big application it will be very difficult to reason about its state.
Certainly.
class ContainerConfig(object):
def __init__(self):
injector = inject.configure_once(self.create_bindings)
def provide_my_class(self) -> MyClass:
# Construct and return MyClass instance
return MyClass()
def create_bindings(self, binder):
binder.bind(MyClass, self.provide_my_class())
binder.bind(MyAbstractClass, MyConcreteClass) # this binding style is difficult to override
class TestContainerConfig(ContainerConfig):
# overriding provider functions in a derived class works fine
def provide_my_class(self) -> MyClass:
# Construct and return MyClassStub instance
return MyClassStub()
def create_bindings(self, binder):
super().create_bindings()
binder.bind(MyAbstractClass, MyStubClass) # cannot do this, results in error
Now, I realize that I could have simply created a provider function for my example that I could have then overriden in my TestContainerConfig class, it's just additional/unnecessary steps to accomplish the end goal. The goal here is to allow for a single base configuration that can be overridden as necessary.
An alternative would be to allow for runtime bindings or explicit clearing of bindings. I know you're not very keen on runtime bindings either, however, this would allow for individual tests to easily swap a dependency with a stub. Calling clear_and_reconfigure
wipes out the entire configuration which is far too tedious to reconstruct in individual tests.
At the end of the day, what I'm searching for is a simple method to allow for swapping of dependencies in my tests without having to rebuild the entire configuration or maintain a separate configuration.
Sorry for the delay. I'm travelling right now.
I think, no changes are needed for python-inject. You can always implement your own configuration the way you want. For example, you can create a callable class with provider-methods (as you have already mentioned), inherit it and override the methods you need. Or you can group all your providers in a map then iterate over it and call binder.bind(cls, provider). Etc.
However, I think injector should be immutable and simple. Immutability equals thread-safety. Simplicity allows to easily reason about its state.
If you don't mind, please, close the issue.
Currently, if you create a binding where a binding already exists for the for the given key, an exception is thrown:
inject.InjectorException: Duplicate binding, key=<class 'someValue'>
In many DI frameworks, it's common to allow binding of an existing key to a new value, the behavior for which is to replace the existing binding. For example, Angular uses a hierarchical injector that allows children to override their parent bindings. Autofac uses the last registration/binding for a given key, value.
An example use case:
I have a set of binding configurations that my app uses. I then have a separate test configuration that inherits from my app bindings. If I'm using provider functions, its simple to override them, however if I'm doing simple binding of a Class/value to a value, then I don't have easy way to override the binding.
I realize that there are workarounds for this, but I think this would be simple to implement and provide value to the framework as well as align the duplicate binding behavior to other DI frameworks.