Added logic to handle scoped services
This commit is contained in:
18
src/cpl_core/dependency_injection/scope.py
Normal file
18
src/cpl_core/dependency_injection/scope.py
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
from cpl_core.console.console import Console
|
||||
from cpl_core.dependency_injection.scope_abc import ScopeABC
|
||||
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
|
||||
|
||||
|
||||
class Scope(ScopeABC):
|
||||
|
||||
def __init__(self, service_provider: ServiceProviderABC):
|
||||
self._service_provider = service_provider
|
||||
self._service_provider.set_scope(self)
|
||||
|
||||
@property
|
||||
def service_provider(self) -> ServiceProviderABC:
|
||||
return self._service_provider
|
||||
|
||||
def dispose(self):
|
||||
self._service_provider = None
|
24
src/cpl_core/dependency_injection/scope_abc.py
Normal file
24
src/cpl_core/dependency_injection/scope_abc.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
class ScopeABC(ABC):
|
||||
r"""ABC for the class :class:`cpl_core.dependency_injection.scope.Scope`"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def service_provider(self):
|
||||
r"""Returns to service provider of scope
|
||||
|
||||
Returns
|
||||
-------
|
||||
Object of type :class:`cpl_core.dependency_injection.service_provider_abc.ServiceProviderABC`
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def dispose():
|
||||
r"""Sets service_provider to None
|
||||
"""
|
||||
pass
|
19
src/cpl_core/dependency_injection/scope_builder.py
Normal file
19
src/cpl_core/dependency_injection/scope_builder.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from cpl_core.dependency_injection.scope import Scope
|
||||
from cpl_core.dependency_injection.scope_abc import ScopeABC
|
||||
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
|
||||
|
||||
|
||||
class ScopeBuilder:
|
||||
r"""Class to build :class:`cpl_core.dependency_injection.scope.Scope`"""
|
||||
|
||||
def __init__(self, service_provider: ServiceProviderABC) -> None:
|
||||
self._service_provider = service_provider
|
||||
|
||||
def build(self) -> ScopeABC:
|
||||
r"""Returns scope
|
||||
|
||||
Returns
|
||||
-------
|
||||
Object of type :class:`cpl_core.dependency_injection.scope.Scope`
|
||||
"""
|
||||
return Scope(self._service_provider)
|
@@ -4,5 +4,5 @@ from enum import Enum
|
||||
class ServiceLifetimeEnum(Enum):
|
||||
|
||||
singleton = 0
|
||||
scoped = 1 # not supported yet
|
||||
scoped = 1
|
||||
transient = 2
|
||||
|
@@ -1,10 +1,13 @@
|
||||
from collections import Callable
|
||||
import copy
|
||||
from inspect import signature, Parameter
|
||||
from typing import Optional
|
||||
|
||||
from cpl_core.configuration.configuration_abc import ConfigurationABC
|
||||
from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC
|
||||
from cpl_core.database.context.database_context_abc import DatabaseContextABC
|
||||
from cpl_core.dependency_injection.scope_abc import ScopeABC
|
||||
from cpl_core.dependency_injection.scope_builder import ScopeBuilder
|
||||
from cpl_core.dependency_injection.service_provider_abc import ServiceProviderABC
|
||||
from cpl_core.dependency_injection.service_descriptor import ServiceDescriptor
|
||||
from cpl_core.dependency_injection.service_lifetime_enum import ServiceLifetimeEnum
|
||||
@@ -30,6 +33,7 @@ class ServiceProvider(ServiceProviderABC):
|
||||
self._service_descriptors: list[ServiceDescriptor] = service_descriptors
|
||||
self._configuration: ConfigurationABC = config
|
||||
self._database_context = db_context
|
||||
self._scope: Optional[ScopeABC] = None
|
||||
|
||||
def _find_service(self, service_type: type) -> ServiceDescriptor:
|
||||
for descriptor in self._service_descriptors:
|
||||
@@ -84,8 +88,15 @@ class ServiceProvider(ServiceProviderABC):
|
||||
params.append(self._get_service(parameter))
|
||||
|
||||
return service_type(*params)
|
||||
|
||||
def set_scope(self, scope: ScopeABC):
|
||||
self._scope = scope
|
||||
|
||||
def create_scope(self) -> ScopeABC:
|
||||
sb = ScopeBuilder(ServiceProvider(copy.deepcopy(self._service_descriptors), self._configuration, self._database_context))
|
||||
return sb.build()
|
||||
|
||||
def get_service(self, service_type: type) -> Optional[Callable]:
|
||||
def get_service(self, service_type: type) -> Optional[Callable[object]]:
|
||||
result = self._find_service(service_type)
|
||||
|
||||
if result is None:
|
||||
@@ -95,7 +106,7 @@ class ServiceProvider(ServiceProviderABC):
|
||||
return result.implementation
|
||||
|
||||
implementation = self.build_service(service_type)
|
||||
if result.lifetime == ServiceLifetimeEnum.singleton:
|
||||
if result.lifetime == ServiceLifetimeEnum.singleton or result.lifetime == ServiceLifetimeEnum.scoped and self._scope is not None:
|
||||
result.implementation = implementation
|
||||
|
||||
return implementation
|
||||
|
@@ -2,6 +2,8 @@ from abc import abstractmethod, ABC
|
||||
from collections import Callable
|
||||
from typing import Type, Optional
|
||||
|
||||
from cpl_core.dependency_injection.scope_abc import ScopeABC
|
||||
|
||||
|
||||
class ServiceProviderABC(ABC):
|
||||
r"""ABC for the class :class:`cpl_core.dependency_injection.service_provider.ServiceProvider`"""
|
||||
@@ -24,9 +26,30 @@ class ServiceProviderABC(ABC):
|
||||
Object of the given type
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def set_scope(self, scope: ScopeABC):
|
||||
r"""Sets the scope of service provider
|
||||
|
||||
Parameter
|
||||
---------
|
||||
scope :class:`cpl_core.dependency_injection.scope.Scope`
|
||||
Service scope
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def create_scope(self) -> ScopeABC:
|
||||
r"""Creates a service scope
|
||||
|
||||
Returns
|
||||
-------
|
||||
Object of type :class:`cpl_core.dependency_injection.scope.Scope`
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_service(self, instance_type: Type) -> Optional[Callable]:
|
||||
def get_service(self, instance_type: Type) -> Optional[Callable[object]]:
|
||||
r"""Returns instance of given type
|
||||
|
||||
Parameter
|
||||
|
Reference in New Issue
Block a user