Skip to content

依赖注入 ​

Luolan.QQBot 完全支持 .NET 的依赖注入(DI)体系。

什么是依赖注入? ​

依赖注入是一种设计模式,它将对象的创建和管理交给容器,而不是手动 new。

csharp
// ❌ 不使用 DI:手动管理依赖
var httpClient = new HttpClient();
var tokenManager = new TokenManager(options, httpClient, logger);
var apiClient = new QQBotHttpClient(options, httpClient, tokenManager, logger);
var bot = new QQBotClient(options, httpClient, tokenManager, apiClient, webSocket, events, logger);

// ✅ 使用 DI:容器自动装配
builder.Services.AddQQBot(options => { ... });
// 所有依赖自动注册和注入

DI 注册方法 ​

AddQQBot ​

标准注册方式:

csharp
using Luolan.QQBot.Extensions;

// 委托方式
builder.Services.AddQQBot(options =>
{
    options.AppId = "...";
    options.ClientSecret = "...";
});

// 参数方式
builder.Services.AddQQBot("appId", "clientSecret", isSandbox: true, Intents.Default);

注册的服务(全部为 Singleton):

服务说明
QQBotClientOptions配置选项
EventDispatcher事件分发器
TokenManagerToken 管理器
QQBotHttpClientHTTP API 客户端
QQBotWebSocketClientWebSocket 客户端
QQBotClient机器人客户端主类
ControllerManager控制器管理器(用于 DI 构造控制器)

AddQQBotWithHttpClientFactory ​

使用 IHttpClientFactory 的推荐方式:

csharp
using Luolan.QQBot.Extensions;

builder.Services.AddQQBotWithHttpClientFactory(options =>
{
    options.AppId = "...";
    options.ClientSecret = "...";
});

优势:

  • HttpClient 生命周期由框架管理
  • 自动处理连接池和 Socket 耗尽问题
  • 更好的性能和资源利用率

AddQQBotHostedService ​

注册 IHostedService,自动管理 Bot 的启动和停止:

csharp
builder.Services.AddQQBotHostedService();

Webhook 模式 ​

QQBotWebhook 会由 AddQQBot / AddQQBotWithHttpClientFactory 自动注册,不需要额外调用。切换模式只需配置:

csharp
builder.Services.AddQQBotWithHttpClientFactory(options =>
{
    options.AppId = "...";
    options.ClientSecret = "...";
    options.Mode = QQBotConnectionMode.Webhook;
});

builder.Services.AddQQBotHostedService(); // 两种模式都保留

在 ASP.NET Core 中再加一行 app.MapQQBotWebhook()(需要 Luolan.QQBot.AspNetCore 包)。WebSocket 模式下这行会自动跳过。

模式切换

AddQQBotHostedService() 在 Webhook 模式下不会连接 WebSocket,只做就绪初始化,所以两种模式的启动代码可以完全一致。

注入和使用 ​

在 ASP.NET Core Controller 中 ​

csharp
[ApiController]
public class BotApiController : ControllerBase
{
    private readonly QQBotClient _bot;
    private readonly EventDispatcher _events;

    public BotApiController(QQBotClient bot, EventDispatcher events)
    {
        _bot = bot;
        _events = events;
    }
}

在 Bot 命令控制器中 ​

QQBotController 子类同样支持构造函数注入(v1.5.1 修复了 DI 接线):

csharp
public class HelloController : QQBotController
{
    private readonly ILogger<HelloController> _logger;

    public HelloController(ILogger<HelloController> logger)
    {
        _logger = logger;
    }

    [Command("hello")]
    public string Hello(string name)
    {
        _logger.LogInformation("hello: {Name}", name);
        return $"Hello, {name}!";
    }
}

// Program.cs
var app = builder.Build();
app.Services.GetRequiredService<QQBotClient>().UseControllers();

在托管服务中 ​

csharp
public class CustomBotService : BackgroundService
{
    private readonly QQBotClient _bot;

    public CustomBotService(QQBotClient bot)
    {
        _bot = bot;
    }

    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
        {
            // 使用 _bot...
            await Task.Delay(60000, ct);
        }
    }
}

// 注册
builder.Services.AddHostedService<CustomBotService>();

在 Minimal API 中 ​

csharp
app.MapGet("/bot/status", (QQBotClient bot) => new
{
    Connected = bot.IsConnected,
    Username = bot.CurrentUser?.Username,
    GuildCount = bot.GetGuildsAsync().Result.Count
});

app.MapPost("/bot/send", async (QQBotClient bot, SendMessageDto dto) =>
{
    await bot.SendChannelMessageAsync(dto.ChannelId, dto.Content);
    return Results.Ok();
});

生命周期说明 ​

QQ Bot 的服务都是 Singleton(单例),因为:

  • Bot 客户端在整个应用生命周期中只需要一个实例
  • WebSocket 连接需要持久化
  • Token 缓存状态需要共享
csharp
// 验证生命周期
var bot1 = app.Services.GetRequiredService<QQBotClient>();
var bot2 = app.Services.GetRequiredService<QQBotClient>();
Console.WriteLine(bot1 == bot2); // True — 是同一个实例

手动创建 vs DI ​

csharp
// 适合 ASP.NET Core
builder.Services.AddQQBot(options => { ... });
builder.Services.AddQQBotHostedService();
csharp
// 适合简单的控制台程序
var bot = new QQBotClientBuilder()
    .WithAppId("...")
    .WithClientSecret("...")
    .Build();
await bot.StartAsync();

两种方式可以混合使用,例如在控制台中使用 Builder,同时手动创建 ServiceCollection 注册其他服务。

高级:自定义 DI 注册 ​

如果需要更精细的控制:

csharp
builder.Services.AddSingleton(sp =>
{
    var options = new QQBotClientOptions
    {
        AppId = "...",
        ClientSecret = "..."
    };

    var loggerFactory = sp.GetRequiredService<ILoggerFactory>();
    var httpClient = sp.GetRequiredService<IHttpClientFactory>()
        .CreateClient("QQBot");

    return new QQBotClient(options, loggerFactory);
});

下一步 ​

基于 MIT 协议发布