依赖注入
OpenClaw CLI 使用简洁的依赖注入模式,通过 CliDeps 接口将通道发送函数和其他基础设施能力注入到命令中。
CliDeps 接口
Source: src/cli/deps.ts
typescript
// src/cli/deps.ts (simplified)
interface CliDeps {
sendMessageWhatsApp: SendFunction;
sendMessageTelegram: SendFunction;
sendMessageDiscord: SendFunction;
sendMessageSlack: SendFunction;
sendMessageSignal: SendFunction;
sendMessageIMessage: SendFunction;
}CliDeps 是一个简单的接口,包含所有通道的发送函数。
创建依赖
typescript
// src/cli/deps.ts (simplified)
function createDefaultDeps(): CliDeps {
return {
sendMessageWhatsApp: createWhatsAppSender(),
sendMessageTelegram: createTelegramSender(),
sendMessageDiscord: createDiscordSender(),
sendMessageSlack: createSlackSender(),
sendMessageSignal: createSignalSender(),
sendMessageIMessage: createIMessageSender(),
};
}createDefaultDeps() 工厂函数创建所有通道发送器的具体实现。
桥接到基础设施层
Source: src/cli/deps.ts
typescript
// Bridging CLI deps to infra layer
function createOutboundSendDeps(deps: CliDeps): OutboundSendDeps {
return {
sendWhatsApp: deps.sendMessageWhatsApp,
sendTelegram: deps.sendMessageTelegram,
sendDiscord: deps.sendMessageDiscord,
sendSlack: deps.sendMessageSlack,
sendSignal: deps.sendMessageSignal,
sendIMessage: deps.sendMessageIMessage,
};
}桥接函数将 CLI 层的 CliDeps 转换为基础设施层的 OutboundSendDeps,字段名可能不同但功能一致。
为什么使用依赖注入?
- 可测试性 — 测试中可以注入 mock 发送函数
- 解耦 — CLI 命令不直接依赖具体的通道 SDK
- 灵活性 — 可以替换实现而不修改命令代码
- 一致性 — 所有命令通过统一接口访问通道能力
测试示例
typescript
// In tests, inject mock dependencies
const mockDeps: CliDeps = {
sendMessageTelegram: vi.fn().mockResolvedValue({ messageId: 1 }),
sendMessageDiscord: vi.fn().mockResolvedValue({ messageId: 2 }),
// ...
};
// Command uses injected deps
await sendCommand(mockDeps, { to: "123", message: "test" });
// Verify mock was called
expect(mockDeps.sendMessageTelegram).toHaveBeenCalledWith(/* ... */);小结
- CliDeps 接口包含所有通道的发送函数
- createDefaultDeps() 创建具体实现
- createOutboundSendDeps() 桥接到基础设施层
- 依赖注入提供 可测试性、解耦 和 灵活性
下一章:媒体处理