diff --git a/container.py b/container.py new file mode 100644 index 0000000..8bfd22b --- /dev/null +++ b/container.py @@ -0,0 +1,68 @@ +from dataclasses import dataclass +from types import LambdaType, FunctionType +from typing import Mapping, Type, TypeVar + +T = TypeVar("T") + +class ServiceLookupException(Exception): + pass + +@dataclass +class ServiceContainer: + _singletons: Mapping[str, T] + _factories: Mapping[str, T] + + def register_name(self, name: str, instance: T) -> None: + if type(instance) is LambdaType or type(instance) is FunctionType: + self._factories[name] = instance + else: + self._singletons[name] = instance + + def retrieve_name(self, name: str, _: Type[T]) -> T: + if name in self._singletons: + return self._singletons[name] + elif name in self._factories: + return self._factories[name]() + + raise ServiceLookupException(f"Could not locate service with name {name}") + + def register_type(self, instance: T) -> None: + t = type(instance) + name = str(Type[t]) + if type(instance) is LambdaType or type(instance) is FunctionType: + self._factories[name] = instance + else: + self._singletons[name] = instance + + def retrieve_type(self, desired_type: Type[T]) -> T: + name = str(desired_type) + if name in self._singletons: + return self._singletons[name] + elif name in self._factories: + return self._factories[name]() + + raise ServiceLookupException(f"Could not locate service with name {name}") + + +@dataclass +class Foo: + bar: str + + def __post_init__(self): + print(f"Initialized with {self.bar}") + + +container = ServiceContainer({}, {}) +container.register_name("foo_lam", lambda : Foo("bar")) +foo_single = Foo("baz") +container.register_name("foo_single", foo_single) + +mc1 = container.retrieve_name("foo_lam", Type[Foo]) +mc2 = container.retrieve_name("foo_lam", Type[Foo]) +mc3 = container.retrieve_name("foo_single", Type[Foo]) +mc4 = container.retrieve_name("foo_single", Type[Foo]) + +print(mc1.bar) +print(mc2.bar) +print(mc3.bar) +print(mc4.bar) \ No newline at end of file