forked from p15670423/monkey
Common: Resolve registered instances and types directly
This commit is contained in:
parent
435b619a5d
commit
7a62434364
|
@ -42,24 +42,29 @@ class DIContainer:
|
||||||
:param type_: A type (class) to construct.
|
:param type_: A type (class) to construct.
|
||||||
:return: An instance of `type_`
|
:return: An instance of `type_`
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
|
return self._resolve_type(type_)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
args = []
|
args = []
|
||||||
|
|
||||||
# TODO: Need to handle keyword-only arguments, defaults, varargs, etc.
|
# TODO: Need to handle keyword-only arguments, defaults, varargs, etc.
|
||||||
for arg_type in inspect.getfullargspec(type_).annotations.values():
|
for arg_type in inspect.getfullargspec(type_).annotations.values():
|
||||||
instance = self._resolve_arg_type(arg_type)
|
instance = self._resolve_type(arg_type)
|
||||||
args.append(instance)
|
args.append(instance)
|
||||||
|
|
||||||
return type_(*args)
|
return type_(*args)
|
||||||
|
|
||||||
def _resolve_arg_type(self, arg_type: Type[T]) -> T:
|
def _resolve_type(self, type_: Type[T]) -> T:
|
||||||
if arg_type in self._type_registry:
|
if type_ in self._type_registry:
|
||||||
return self._resolve_type(arg_type)
|
return self._construct_new_instance(type_)
|
||||||
elif arg_type in self._instance_registry:
|
elif type_ in self._instance_registry:
|
||||||
return self._resolve_instance(arg_type)
|
return self._retrieve_registered_instance(type_)
|
||||||
|
|
||||||
raise ValueError(f'Failed to resolve unknown type "{arg_type.__name__}"')
|
raise ValueError(f'Failed to resolve unknown type "{type_.__name__}"')
|
||||||
|
|
||||||
def _resolve_type(self, arg_type: Type[T]) -> T:
|
def _construct_new_instance(self, arg_type: Type[T]) -> T:
|
||||||
try:
|
try:
|
||||||
return self._type_registry[arg_type]()
|
return self._type_registry[arg_type]()
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
@ -67,7 +72,7 @@ class DIContainer:
|
||||||
# construct an instance of arg_type with all of the requesite dependencies injected.
|
# construct an instance of arg_type with all of the requesite dependencies injected.
|
||||||
return self.resolve(self._type_registry[arg_type])
|
return self.resolve(self._type_registry[arg_type])
|
||||||
|
|
||||||
def _resolve_instance(self, arg_type: Type[T]) -> T:
|
def _retrieve_registered_instance(self, arg_type: Type[T]) -> T:
|
||||||
return self._instance_registry[arg_type]
|
return self._instance_registry[arg_type]
|
||||||
|
|
||||||
def release(self, interface: Type[T]):
|
def release(self, interface: Type[T]):
|
||||||
|
|
|
@ -6,7 +6,9 @@ from common import DIContainer
|
||||||
|
|
||||||
|
|
||||||
class IServiceA(metaclass=abc.ABCMeta):
|
class IServiceA(metaclass=abc.ABCMeta):
|
||||||
pass
|
@abc.abstractmethod
|
||||||
|
def do_something(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class IServiceB(metaclass=abc.ABCMeta):
|
class IServiceB(metaclass=abc.ABCMeta):
|
||||||
|
@ -14,7 +16,8 @@ class IServiceB(metaclass=abc.ABCMeta):
|
||||||
|
|
||||||
|
|
||||||
class ServiceA(IServiceA):
|
class ServiceA(IServiceA):
|
||||||
pass
|
def do_something(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ServiceB(IServiceB):
|
class ServiceB(IServiceB):
|
||||||
|
@ -117,7 +120,8 @@ def test_unregistered_type():
|
||||||
|
|
||||||
def test_type_registration_overwritten(container):
|
def test_type_registration_overwritten(container):
|
||||||
class ServiceA2(IServiceA):
|
class ServiceA2(IServiceA):
|
||||||
pass
|
def do_something(self):
|
||||||
|
pass
|
||||||
|
|
||||||
container.register(IServiceA, ServiceA)
|
container.register(IServiceA, ServiceA)
|
||||||
container.register(IServiceA, ServiceA2)
|
container.register(IServiceA, ServiceA2)
|
||||||
|
@ -229,3 +233,20 @@ def test_recursive_resolution__depth_3(container):
|
||||||
assert isinstance(test5.service_d.service_b, ServiceB)
|
assert isinstance(test5.service_d.service_b, ServiceB)
|
||||||
assert isinstance(test5.service_d.service_c, ServiceC)
|
assert isinstance(test5.service_d.service_c, ServiceC)
|
||||||
assert isinstance(test5.service_d.service_c.service_a, ServiceA)
|
assert isinstance(test5.service_d.service_c.service_a, ServiceA)
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_registered_interface(container):
|
||||||
|
container.register(IServiceA, ServiceA)
|
||||||
|
|
||||||
|
resolved_instance = container.resolve(IServiceA)
|
||||||
|
|
||||||
|
assert isinstance(resolved_instance, ServiceA)
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_registered_instance(container):
|
||||||
|
service_a_instance = ServiceA()
|
||||||
|
container.register_instance(IServiceA, service_a_instance)
|
||||||
|
|
||||||
|
service_a_actual_instance = container.resolve(IServiceA)
|
||||||
|
|
||||||
|
assert id(service_a_actual_instance) == id(service_a_instance)
|
||||||
|
|
Loading…
Reference in New Issue