代理 (Proxy) 模式
Tip
关于这里所提到的 Dispatcher 的调用顺序问题, 简单的答复你可以参考 dispatcher-mixin 一章, 如果需要更详细的, 记住一句话, 这句话也是我们在开发时遵循的规范:
局部先于全局, 有既是有, 无既是无.
我们在上一章中简单的提到了 Dispatcher 的调用顺序问题, 那么, 我们便可以利用这点, 在调用顺序更优先的 Dispatcher 内获取到本应在事件监听器里才能获取到的值.
一般的, 我们的 Dispatcher 是长这样的:
class TestDispatcher(BaseDispatcher):
mixin = [...]
async def catch(self, interface: DispatcherInterface):
...
顶多也就是当作为事件本身提供的 Dispatcher 的时候, catch
方法是个 staticmethod
而已.
那么, 我们在上一章, 所提到的 mixin
机制, 在实际使用时, 偶尔也会有 "需要重载行为" 的需求, 那么, 我们又不想 copy & paste, 也不想将这些 mixin 分割成更小的单元, 我们就可以用上 DispatcherInterface
里用到的一些方法.
Tip
这里, 我想我不免的要提上一嘴. 我的作品足够聪明, 不需要你去关心 "欸这样会不会丢掉 Fastest Path 啊" 这样的问题, 尽管你可能完全不知道这里说的 "Fastest Path" 是什么, 这就是一个极其卓越的优化机制而已, 现在的性能大多托此所赐.
使用 DispatcherInterface.lookup_param
方法, 即可模拟对实际参数的解析.
await interface.lookup_param(
"_what_is_me", str, None
)
这里的参数, 从左到右分别是 名称, 类型注解 和 默认值.
Warning
无论如何, 除非你用了某种魔法, 否则你不应该能在这里使用 Decorator
.
这样, 你就能够获得你想要的值, 对其进行包装后扔到外面去, 也就是 return
出去.
Tip
其实, 你也不必扔外面, 但这可能会让某个 Dispatcher 被调用两次, 造成内存泄漏, 所以我建议你还是多做推理, 以避免出现这样的情况. 人胜过机器的永远是方法这方面.......吧?
如果你要丢一个可能会被当作特殊处理的对象, 比如说 None
, 你可以使用 Force
.
from graia.broadcast.entities.signatures import Force
return Force(None)
对于我们来说, Force(Force(None))
就等同于 Force(None)
, 这有助于避免用到一些奇怪的, 非常难以维护的魔法.