melobot.di

依赖注入部件

class melobot.di.Depends[源代码]

基类:Generic[T]

__init__(dep: SyncOrAsyncCallable[(), T] | Depends[T], sub_getter: SyncOrAsyncCallable[T, T] | None = None, cache: bool = False, recursive: bool = True) None[源代码]

初始化一个依赖项

参数:
  • dep (SyncOrAsyncCallable[(), T] | Depends[T]) -- 依赖来源(可调用对象,异步可调用对象,或依赖项)

  • sub_getter (SyncOrAsyncCallable[(~T,), T] | None) -- 子获取器(可调用对象,异步可调用对象或空),在获得依赖之后,于其上继续获取

  • cache (bool) -- 是否启用缓存

  • recursive (bool) -- 是否启用递归满足(默认启用,如果当前依赖来源中存在依赖项,会被递归满足;关闭可节约性能)

返回类型:

None

class melobot.di.DependsHook[源代码]

基类:Depends[T], BetterABC

依赖钩子

包装一个依赖项,依赖满足后内部的 hook 将会执行

__init__(dep: SyncOrAsyncCallable[(), T], cache: bool = False, recursive: bool = False) None[源代码]

初始化一个依赖项

参数:
  • dep (SyncOrAsyncCallable[(), T]) -- 依赖来源(可调用对象,异步可调用对象,或依赖项)

  • sub_getter -- 子获取器(可调用对象,异步可调用对象或空),在获得依赖之后,于其上继续获取

  • cache (bool) -- 是否启用缓存

  • recursive (bool) -- 是否启用递归满足(默认启用,如果当前依赖来源中存在依赖项,会被递归满足;关闭可节约性能)

返回类型:

None

abstract async deps_callback(val: T) None[源代码]

所有依赖钩子子类必须实现该抽象方法

参数:

val (T) -- 依赖项被满足后的值

返回类型:

None

melobot.di.inject_deps(injectee: SyncOrAsyncCallable[..., T], manual_arg: bool = False) AsyncCallable[..., T][源代码]

依赖注入标记装饰器,标记当前对象需要被依赖注入

可以标记的对象类别有: 同步函数,异步函数,匿名函数,同步生成器函数,异步生成器函数,实例方法、类方法、静态方法

参数:
  • injectee (SyncOrAsyncCallable[..., T]) -- 需要被注入的对象

  • manual_arg (bool) -- 当前对象标记需要依赖注入后,是否还可以给某些参数手动传参

返回:

异步可调用对象,但保留原始参数和返回值签名

返回类型:

AsyncCallable[..., T]

依赖注入元数据标记

依赖注入时用作 Annotated 元数据

class melobot.di.Exclude[源代码]

基类:object

数据类。types 指定的类别会在依赖注入时被排除

# 假设有继承关系 A <- B, A <- C, A <- D
# 表示 A 中不包括 B 和 C 类别的所有子类型,当然,还是会兼容 A 类型本身
NewTypeHint = Annotated[A, Exclude(types=[B, C])]
types: Sequence[type]
class melobot.di.CustomLogger[源代码]

基类:object

数据类。getter 参数会用于指定类别日志器不存在时的获取方法

# 如果 bot 设置的 logger 是 MyLogger 类型,则成功依赖注入
# 否则使用 getter 获取一个日志器
NewLoggerHint = Annotated[MyLogger, CustomLogger(getter=MyLogger)]
getter: Callable[[], Any]
class melobot.di.Reflect[源代码]

基类:object

数据类。指定不直接获取当前依赖项,而是获取对应的一个反射代理

这适用于希望依赖会随着上下文改变,而动态变化的情况。例如动态引用会话流程中的事件对象

# 注入一个依赖时进一步包装为反射依赖
event_proxy = Annotated[Event, Reflect()]
# 就像使用 event 一样使用 event_proxy
event_proxy.attr_xxx
event_proxy.method_xxx()

# 不过 event_proxy 不是完美的代理
# 因此 isinstance 类似的操作,使用 __origin__ 获取原始对象
isinstance(event_proxy.__origin__, SomeEventType)
# 或者是作为运行逻辑未知的函数的参数
dont_know_what_this_do(event_proxy.__origin__)
class melobot.di.MatchEvent[源代码]

基类:object

数据类。指定从当前事件的上下文中获取依赖

默认情况下,获取 Adapter 依赖都会直接尝试遍历所有可能的对象。

即尽最大可能获取指定类型的对象。但有时需要实现这样的需求:

# 假设 bot 已经加载了两个适配器:ObAdapter 和 XxAdapter
from melobot.handle import on_event
# 期待事件来自 ObAdapter 时,调用这个
@on_event()
async def on_onebot_event(adapter: ObAdapter) -> None: ...
# 期待事件来自 XxAdapter 时,调用这个
@on_event()
async def on_xx_event(adapter: XxAdapter) -> None: ...

# 但默认的逻辑是:bot 只要加载了对应的适配器,依赖就可以满足
# 所以实际上他们都会被调用,没有任何区分效果

# 使用 MatchEvent 来改变依赖获取的逻辑:
# 事件的来源适配器必须和 MatchEvent 中指定的类型匹配,依赖才能满足
@on_event()
async def on_onebot_event(adapter: Annotated[ObAdapter, MatchEvent()]) -> None: ...
@on_event()
async def on_xx_event(adapter: Annotated[XxAdapter, MatchEvent()]) -> None: ...