Как работать с Dependency Injections
Dependency Injection (DI) — это шаблон проектирования, который позволяет упростить управление зависимостями между компонентами программы.
Часто бывает, что есть некоторые служебные классы, которые необходимы в большом количестве других мест. Самый простой способ реализации — создать глобальный экземпляр, который будет доступен отовсюду.
Например, такой подход используется с g_eventBus:
from gui.shared import g_eventBusОднако этот подход имеет множество недостатков: жёсткая связь между классами, сложность тестирования и трудности в управлении жизненным циклом объектов.
Чтобы решить эти проблемы был придуман шаблон Dependency Injection.
Инъекция зависимостей
Чтобы получить ссылку на класс, в игре используется модуль helpers.dependency. Классы, которые можно получить через DI, определяются их интерфейсами, что позволяет легко заменять реализации без изменения кода, который их использует.
Одним из таких интерфейсов является распространённый IItemsCache, который предоставляет доступ к данным об игроке, его танках, экипаже и т. д.
Получить ссылку на реализацию интерфейса можно несколькими способами:
@dependency.replace_none_kwargs– заменяет параметры функцииdependency.instance– получить экземпляр здесь и сейчасdependency.descriptor– определить зависимость как дескриптор класса
Если у вас настроен VSCode с подсказками для игры, необходимо ставить аннотации типов, чтобы редактор понимал, какой тип будет возвращён. Аннотации ставятся через комментарий # type: <тип>.
@dependency.replace_none_kwargs
Позволяет автоматически внедрять зависимости в параметры функции или метода, если они не были переданы явно.
from helpers import dependency
from skeletons.gui.shared import IItemsCache
@dependency.replace_none_kwargs(itemsCache=IItemsCache)
def demo(foo, bar, itemsCache=None):
# type: (str, str, IItemsCache) -> None
print(itemsCache)
demo('foo', 'bar') # itemsCache будет автоматически внедрёнdependency.instance
Позволяет получить экземпляр здесь и сейчас.
from helpers import dependency
from skeletons.gui.shared import IItemsCache
itemsCache = dependency.instance(IItemsCache) # type: IItemsCache
print(itemsCache)dependency.descriptor
Позволяет определить зависимость как дескриптор класса. Зависимость будет автоматически внедрена при создании экземпляра класса.
from helpers import dependency
from skeletons.gui.shared import IItemsCache
class Demo:
itemsCache = dependency.descriptor(IItemsCache) # type: IItemsCache
def showItemsCache(self):
print(self.itemsCache)
demo = Demo()Полезные интерфейсы
Вот список некоторых полезных интерфейсов, которые могут пригодиться при разработке модов
TODO
Расписать подробнее
IItemsCache
Предоставляет доступ к данным об игроке, его танках, экипаже, бейджах, достижениях и т.д.
from helpers import dependency
from skeletons.gui.shared import IItemsCache
itemsCache = dependency.instance(IItemsCache) # type: IItemsCache
print(itemsCache.items.stats) # Доступ к статистике игрока
print(itemsCache.items.getVehicles()) # Доступ к танкам игрокаIHangarSpace
Предоставляет доступ к пространству ангара, позволяет подписываться на события создания и уничтожения пространства.
from helpers import dependency
from skeletons.gui.shared.utils import IHangarSpace
hangarSpace = dependency.instance(IHangarSpace) # type: IHangarSpace
hangarSpace.onSpaceCreate += lambda: print("Ангар создан")
hangarSpace.onSpaceDestroy += lambda: print("Ангар уничтожен")
hangarSpace.onVehicleChanged += lambda: print("Танк в ангаре изменён")IBattleSessionProvider
Предоставляет доступ к данным о бое, позволяет подписываться на события начала и окончания боя.
from helpers import dependency
from skeletons.gui.battle_session import IBattleSessionProvider
sessionProvider = dependency.instance(IBattleSessionProvider) # type: IBattleSessionProvider
sessionProvider.onBattleSessionStart += lambda: print("Бой начался")
sessionProvider.onBattleSessionStop += lambda: print("Бой закончился")
print(sessionProvider.isReplayPlaying) # Проверка, находится ли в данный момент воспроизведение реплеяIEventsCache
Предоставляет доступ к данным о событиях, таких как кланы, рейтинговые бои.
from helpers import dependency
from gui.server_events import IEventsCache
eventsCache = dependency.instance(IEventsCache) # type: IEventsCache
print(eventsCache.getAllQuests()) # Доступ ко всем задачам
print(eventsCache.getPersonalMissions()) # Доступ к ЛБЗILobbyContext
???
from helpers import dependency
from skeletons.gui.lobby_context import ILobbyContext
lobbyContext = dependency.instance(ILobbyContext) # type: ILobbyContext
Andrei Soprachev