-
Notifications
You must be signed in to change notification settings - Fork 86
[Enhancement] Allow calling methods and injecting their parameters #62
Description
Problem
A lot of times I just want to call a function which has arguments that need to be injected. In order to call the function like thisI basically have to create a wrapper class for the function which specifies the arguments required, and then call some method on the wrapper to pass in the injected arguments. This works but is a lot of boilerplate. e.g.
def foobar(foo: Foo) -> int:
...
class FoobarWrapper:
def __init__(foo: Foo) -> None:
self.foo = foo
def call(self): -> int:
return foobar(self.foo)
obj_graph = new_object_graph()
print("foobar returns:", obj_graph.provide(FoobarWrapper).call())Solution
I want to be able to call functions with arbitrary parameters and have pinject construct all of the necessary inputs for me.
It seems like the library is set up nicely to support this, however, it requires me to access private members of the ObjectGraph instance.
Proof of Concept
After browsing through the implementation, I've been able to achieve my goal with the following 3 line hack. I provide a helper method around it to keep things simple and type-safe.
from typing import TypeVar, Callable
from pinject.object_graph import ObjectGraph
T = TypeVar("T")
def inject_func(obj_graph: ObjectGraph, func: Callable[..., T]) -> T:
context = obj_graph._injection_context_factory.new(func)
args, kwargs = obj_graph._obj_provider.get_injection_pargs_kwargs(func, context, [], {})
return func(*args, **kwargs)And here's how you'd call it:
class Bar:
def __init__(self) -> None:
self.a = 1
class Foo:
def __init__(self, bar: Bar) -> None:
self.bar = bar
def foobar(foo: Foo) -> int:
return foo.bar.a
obj_graph = new_object_graph()
print("foobar returns:", inject_func(obj_graph, foobar))foobar returns: 1
Desired Implementation
What I'd like to see is something like this at the same level as ObjectGraph.provide. Maybe ObjectGraph.invoke
obj_graph = new_object_graph()
print("foobar returns:", obj_graph.invoke(foobar))