Update Architecture.py

This commit is contained in:
2025-09-25 11:52:26 +08:00
parent 6331c8e025
commit 4010d9dd8c

View File

@@ -5,28 +5,38 @@ from abc import ABC, abstractmethod
class ISignal(ABC): class ISignal(ABC):
pass pass
class IModel(ABC): class IModel(ABC):
pass
class IDataModel(ABC, IModel):
@abstractmethod @abstractmethod
def Save(self) -> str: def Save(self) -> str:
pass pass
@abstractmethod @abstractmethod
def Load(self, data:str) -> None: def Load(self, data:str) -> None:
pass pass
class IConvertable[T](ABC): class IConvertable[T](ABC):
@abstractmethod @abstractmethod
def ConvertTo(self) -> T: def ConvertTo(self) -> T:
pass pass
class IConvertModel[T](IConvertable[T], IModel): class IConvertModel[T](IConvertable[T], IModel):
pass pass
class SingletonModel[T](IModel): class SingletonModel[T](IModel):
_InjectInstances:Dict[type,Any] = {} _InjectInstances:Dict[type,Any] = {}
@staticmethod @staticmethod
def GetInstance(t:Typen[T]) -> T: def GetInstance(t:Typen[T]) -> T:
return SingletonModel._InjectInstances[t] return SingletonModel._InjectInstances[t]
@staticmethod @staticmethod
def SetInstance(t:Typen[T], obj:T) -> None: def SetInstance(t:Typen[T], obj:T) -> None:
SingletonModel._InjectInstances[t] = obj SingletonModel._InjectInstances[t] = obj
@@ -34,9 +44,6 @@ class SingletonModel[T](IModel):
def __init__(self, t:Typen[T]) -> None: def __init__(self, t:Typen[T]) -> None:
self.typen: type = t self.typen: type = t
@override
def Save(self) -> str:
return SingletonModel.GetInstance(self.typen).Save()
class DependenceModel(IConvertModel[bool]): class DependenceModel(IConvertModel[bool]):
def __init__(self, queries:Sequence[IConvertModel[bool]]) -> None: def __init__(self, queries:Sequence[IConvertModel[bool]]) -> None:
@@ -52,14 +59,10 @@ class DependenceModel(IConvertModel[bool]):
def __iter__(self): def __iter__(self):
return iter(self.queries) return iter(self.queries)
def Load(self, data:str):
raise NotImplementedError()
def Save(self) -> str:
raise NotImplementedError()
SignalListener = Callable[[ISignal], None] SignalListener = Callable[[ISignal], None]
class Architecture: class Architecture:
@staticmethod @staticmethod
def FormatType(t:type) -> str: def FormatType(t:type) -> str:
@@ -78,14 +81,11 @@ class Architecture:
@classmethod @classmethod
def InternalReset(cls) -> None: def InternalReset(cls) -> None:
# Register System # Register System
cls._RegisterHistory.clear() cls._RegisteredObjects.clear()
cls._UncompleteTargets.clear() cls._RegisteringRuntime.clear()
cls._Completer.clear() # Signal Listener
cls._Dependences.clear()
cls._Childs.clear()
# Event Listener
cls._SignalListener.clear() cls._SignalListener.clear()
# Linear Chain for Dependence # Timeline/Chain
cls._TimelineQueues.clear() cls._TimelineQueues.clear()
cls._TimelineContentID = 0 cls._TimelineContentID = 0
@@ -97,136 +97,79 @@ class Architecture:
@override @override
def ConvertTo(self) -> bool: def ConvertTo(self) -> bool:
return self._queryType in Architecture._Childs return self._queryType in Architecture._RegisteredObjects
def Load(self, data:str) -> None:
raise NotImplementedError()
def Save(self) -> str:
raise NotImplementedError()
_RegisterHistory: Set[type] = set()
_UncompleteTargets: Dict[type,Any] = {}
_Completer: Dict[type,Action] = {}
_Dependences: Dict[type,DependenceModel] = {}
_Childs: Dict[type,Any] = {}
class Registering(IConvertModel[bool]): class Registering(IConvertModel[bool]):
def __init__(self,registerSlot:type) -> None: def __init__(self, registerSlot:type, target:Any, dependences:DependenceModel, action:Action) -> None:
self._registerSlot:type = registerSlot self.registerSlot = registerSlot
self.target = target
self.dependences = dependences
self.action = action
@override @override
def ConvertTo(self) -> bool: def ConvertTo(self) -> bool:
return self._registerSlot in Architecture._Childs return self.dependences.ConvertTo()
@override _RegisteringRuntime: Dict[type, Registering] = {}
def Load(self,data:str) -> None: _RegisteredObjects: Dict[type, Any] = {}
raise InvalidOperationError(f"Cannot use {self.__class__.__name__} to load type")
@override
def Save(self) -> str:
return f"{Architecture.FormatType(self._registerSlot)}[{self.ConvertTo()}]"
@classmethod @classmethod
def _InternalRegisteringComplete(cls) -> tuple[bool,Set[type]]: def _InternalRegisteringComplete(cls) -> None:
resultSet: Set[type] = set() CompletedSet: Set[Architecture.Registering] = set()
stats: bool = False for dependence in cls._RegisteringRuntime.keys():
for dependence in cls._Dependences.keys(): if cls._RegisteringRuntime[dependence].dependences.ConvertTo():
if cls._Dependences[dependence].ConvertTo(): CompletedSet.add(cls._RegisteringRuntime[dependence])
resultSet.add(dependence) for complete in CompletedSet:
stats = True del cls._RegisteringRuntime[complete.registerSlot]
return stats,resultSet complete.action()
cls._RegisteredObjects[complete.registerSlot] = complete.target
if len(CompletedSet) > 0:
cls._InternalRegisteringComplete()
@classmethod @classmethod
def _InternalRegisteringUpdate(cls, internalUpdateBuffer:Set[type]): def Register(cls, slot:type, target:Any, action:Action, *dependences:type) -> DependenceModel:
for complete in internalUpdateBuffer: if slot in cls._RegisteringRuntime:
cls._Dependences.pop(complete, None)
for complete in internalUpdateBuffer:
cls._Completer[complete]()
cls._Completer.pop(complete, None)
for complete in internalUpdateBuffer:
cls._Childs[complete] = cls._UncompleteTargets[complete]
cls._UncompleteTargets.pop(complete, None)
@classmethod
def Register(cls, slot:type, target:Any, completer:Action, *dependences:type) -> 'Architecture.Registering':
if slot in cls._RegisterHistory:
raise InvalidOperationError("Illegal duplicate registrations") raise InvalidOperationError("Illegal duplicate registrations")
cls._RegisteringRuntime[slot] = Architecture.Registering(slot, target, DependenceModel(Architecture.TypeQuery(dependence) for dependence in dependences), action)
cls._RegisterHistory.add(slot) cls._InternalRegisteringComplete()
cls._Completer[slot] = completer return cls._RegisteringRuntime[slot].dependences
cls._UncompleteTargets[slot] = target
# 过滤掉自身依赖
filtered_deps = [dep for dep in dependences if dep != slot]
type_queries = [cls.TypeQuery(dep) for dep in filtered_deps]
cls._Dependences[slot] = DependenceModel(type_queries)
while True:
has_complete, buffer = cls._InternalRegisteringComplete()
if not has_complete:
break
cls._InternalRegisteringUpdate(buffer)
return cls.Registering(slot)
@classmethod
def RegisterGeneric[T](cls, target:T, completer:Action, *dependences:type) -> 'Architecture.Registering':
return cls.Register(type(target), target, completer, *dependences)
@classmethod @classmethod
def Contains(cls, type_:type) -> bool: def Contains(cls, type_:type) -> bool:
return type_ in cls._Childs return type_ in cls._RegisteredObjects
@classmethod
def ContainsGeneric[T](cls) -> bool:
return cls.Contains(type(T))
@classmethod
def InternalGet(cls, type_:type) -> Any:
return cls._Childs[type_]
@classmethod @classmethod
def Get(cls, type_:type) -> Any: def Get(cls, type_:type) -> Any:
return cls.InternalGet(type_) return cls._RegisteredObjects[type_]
@classmethod @classmethod
def GetGeneric[T](cls) -> T: def Unregister(cls, slot:type) -> bool:
return cls.Get(type(T)) if slot in cls._RegisteredObjects:
del cls._RegisteredObjects[slot]
return True
if slot in cls._RegisteringRuntime:
del cls._RegisteringRuntime[slot]
return True
return False
#endregion #endregion
#region Signal & Update #region Signal & Update
_SignalListener: Dict[type, Set[SignalListener]] = {} _SignalListener: Dict[type, List[SignalListener]] = {}
class Listening:
def __init__(self, action:SignalListener, type_:type):
self._action = action
self._type = type_
def StopListening(self):
if self._type in Architecture._SignalListener:
Architecture._SignalListener[self._type].discard(self._action)
@classmethod @classmethod
def AddListenerGeneric[Signal](cls, slot:type, listener:SignalListener) -> 'Architecture.Listening': def AddListener(cls, slot:type, listener:SignalListener) -> None:
if slot not in cls._SignalListener: if slot not in cls._SignalListener:
cls._SignalListener[slot] = set() cls._SignalListener[slot] = []
def action(signal:ISignal): cls._SignalListener[slot].append(listener)
if isinstance(signal, slot):
listener(signal)
result = cls.Listening(action, slot)
cls._SignalListener[slot].add(action)
return result
@classmethod @classmethod
def SendMessage(cls, slot:type, signal:ISignal): def SendMessage(cls, slot:type, signal:ISignal):
if slot in cls._SignalListener: if slot in cls._SignalListener:
for action in cls._SignalListener[slot]: for listener in cls._SignalListener[slot]:
action(signal) listener(signal)
#endregion #endregion
@@ -285,6 +228,3 @@ class Architecture:
#endregion #endregion