Allow auto resolving partial constructor arguments in lambda
When you need to be explicit about just some constructor argument, it would be nice to not have to specify all other constructor arguments. Ie from the documentation
container[SomeClass] = lambda c: SomeClass(c[SomeOtherDep], "spinning")
could be changed to something like;
container[SomeClass] = lambda c: SomeClass(text="spinning", **c.resolve_args[SomeClass])
Convenient when your class has a lot of injections, and more importantly avoids the coupling of having to depend on all constructor arguments at bind time.
I realized that maybe this only works if the particular argument can not be resolved so it is guaranteed to not be included in what resolve_args() returns. But that is the standard use case.
Another, maybe cleaner way to solve it would be something like this;
container[SomeClass] = lambda c: (c[str] = "spinning")[SomeClass]
... not sure on the best syntax, but basically doing a local bind just for the lambda.
This is the current I hack I've come up with. Not great but it works;
@dataclass
class Resolver:
parent: Container
c: Container
def setup[T](self, typ: Type[T]) -> T:
self.c[typ] = typ
self.parent[typ] = lambda : self.c.resolve(typ)
def bind[T](self: Container, typ: Type[T], t: T) -> Resolver:
cc = self.clone()
cc[typ] = t
return Resolver(self, cc)
setattr(Container, "bind", bind)
# ...
# FileCache will be bound to img_cache whenever ImageGenerator needs to be resolved
container.bind(FileCache, img_cache).setup(ImageGenerator)
container.bind(FileCache, mp3_cache).setup(AudioGenerator)