【问题标题】:Discord.Net dependency injection - dependency was not found when running commandDiscord.Net 依赖注入 - 运行命令时未找到依赖项
【发布时间】:2020-05-01 16:53:35
【问题描述】:

我正在尝试通过模块构造函数进行依赖注入,它似乎可以工作,因为我可以成功地使用构造函数内部的类,但是每当我运行命令时它就会中断。这是我尝试运行命令时得到的结果:

---> System.InvalidOperationException: Failed to create "AnimeCalendarBot.Modules.InfoModule", dependency "TestService" was not found.
   at Discord.Commands.ReflectionUtils.GetMember(CommandService commands, IServiceProvider services, Type memberType, TypeInfo ownerType)
   at Discord.Commands.ReflectionUtils.<>c__DisplayClass2_0`1.<CreateBuilder>b__0(IServiceProvider services)
   at Discord.Commands.ModuleClassBuilder.<>c__DisplayClass6_0 <<BuildCommand>g__ExecuteCallback|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Discord.Commands.CommandInfo.ExecuteInternalAsync(ICommandContext context, Object[] args, IServiceProvider services)
   --- End of inner exception stack trace ---

但是在运行命令之前,一切都很好。

程序:

public class Program
{
    public static void Main(string[] args)
        => new Program().MainAsync().GetAwaiter().GetResult();

    private readonly DiscordSocketClient _client;
    private readonly CommandService _commands;
    private readonly CommandHandler _commandHandler;
    private readonly IServiceProvider _services;

    private Program()
    {
        _client = new DiscordSocketClient(new DiscordSocketConfig
        {
            LogLevel = LogSeverity.Info,
        });

        _commands = new CommandService(new CommandServiceConfig
        {
            LogLevel = LogSeverity.Info,
            CaseSensitiveCommands = false,
        });

        _services = ConfigureServices();

        _commandHandler = new CommandHandler(_client, _commands, _services);

        _client.Log += Log;
        _commands.Log += Log;
    }

    private static IServiceProvider ConfigureServices()
    {
        var map = new ServiceCollection()
            .AddSingleton(new TestService());

        return map.BuildServiceProvider();
    }

    private static Task Log(LogMessage message)
    {
        switch (message.Severity)
        {
            case LogSeverity.Critical:
            case LogSeverity.Error:
                Console.ForegroundColor = ConsoleColor.Red;
                break;
            case LogSeverity.Warning:
                Console.ForegroundColor = ConsoleColor.Yellow;
                break;
            case LogSeverity.Info:
                Console.ForegroundColor = ConsoleColor.White;
                break;
            case LogSeverity.Verbose:
            case LogSeverity.Debug:
                Console.ForegroundColor = ConsoleColor.DarkGray;
                break;
        }
        Console.WriteLine($"{DateTime.Now,-19} [{message.Severity,8}] {message.Source}: {message.Message} {message.Exception}");
        Console.ResetColor();

        return Task.CompletedTask;
    }

    public async Task MainAsync()
    {
        await _commandHandler.InstallCommandsAsync();

        _client.Log += Log;

        await _client.LoginAsync(TokenType.Bot,
            Environment.GetEnvironmentVariable("AnimeCalendarBotToken"));
        await _client.StartAsync();

        // Block this task until the program is closed.
        await Task.Delay(-1);
    }
}

CommandHandler:

public class CommandHandler
{
    private readonly DiscordSocketClient _client;
    private readonly CommandService _commands;
    private readonly IServiceProvider _services;

    public CommandHandler(DiscordSocketClient client, CommandService commands, IServiceProvider services)
    {
        _client = client;
        _commands = commands;
        _services = services;
    }

    public async Task InstallCommandsAsync()
    {
        _client.MessageReceived += HandleCommandAsync;

        await _commands.AddModulesAsync(assembly: Assembly.GetEntryAssembly(),
                                        services: _services);
    }

    private async Task HandleCommandAsync(SocketMessage messageParam)
    {
        // Don't process the command if it was a system message
        var message = messageParam as SocketUserMessage;
        if (message == null) return;

        // Create a number to track where the prefix ends and the command begins
        int argPos = 0;

        // Determine if the message is a command based on the prefix and make sure no bots trigger commands
        if (!(message.HasCharPrefix('!', ref argPos) ||
            message.HasMentionPrefix(_client.CurrentUser, ref argPos)) ||
            message.Author.IsBot)
            return;

        // Create a WebSocket-based command context based on the message
        var context = new SocketCommandContext(_client, message);

        // Execute the command with the command context we just
        // created, along with the service provider for precondition checks.

        // Keep in mind that result does not indicate a return value
        // rather an object stating if the command executed successfully.
        var result = await _commands.ExecuteAsync(
            context: context,
            argPos: argPos,
            services: null);
    }
}

信息模块:

public class InfoModule : ModuleBase<SocketCommandContext>
{
    private readonly TestService _testService;

    public InfoModule(TestService testService)
    {
        _testService = testService;
        _testService.Start(); // this works
    }

    [Command("startTest")]
    [Summary("Starts test service.")]
    public Task StartTestService()
    {
        _testService.Start();
        return Task.CompletedTask;
    }

    [Command("stopTest")]
    [Summary("Stops test service.")]
    public Task StopTestService()
    {
        _testService.Stop();
        return Task.CompletedTask;
    }
}

测试服务:

public class TestService
{
    private readonly Timer _timer;

    public TestService()
    {
        _timer = new Timer(1000) { AutoReset = true };
        _timer.Elapsed += TimerElapsed;
    }

    private void TimerElapsed(object sender, ElapsedEventArgs e)
    {
        String currentTime = DateTime.Now.ToString();
        Console.WriteLine(currentTime);
    }

    public void Start()
    {
        _timer.Start();
    }

    public void Stop()
    {
        _timer.Stop();
    }
}

【问题讨论】:

  • 您没有将服务提供者传递给 ExecuteAsync

标签: c# dependency-injection discord discord.net


【解决方案1】:

我之前遇到过同样的问题。问题是CommandHandler没有注入服务。

首先,我会像@EnderIce2 的回答那样分配您的服务。

var map = new ServiceCollection()
        .AddSingleton<TestService>()

之后你需要转到CommandHandler 并更改结尾InstallCommandsAsync 方法:

await _commands.AddModulesAsync(assembly: Assembly.GetEntryAssembly(),
                                            services: null);

await _commands.AddModulesAsync(assembly: Assembly.GetEntryAssembly(),
                                            services: _services);

HandleCommandAsync 也是如此;最后更改:

await _commands.ExecuteAsync(
            context: context,
            argPos: argPos,
            services: null);

收件人:

await _commands.ExecuteAsync(
                context: context,
                argPos: argPos,
                services: _services);

【讨论】:

    【解决方案2】:

    在 ConfigureServices 的 Program 上试试这个:

    private static IServiceProvider ConfigureServices()
    {
        var map = new ServiceCollection()
            .AddSingleton<TestService>()
    
        return map.BuildServiceProvider();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-24
      • 2012-11-23
      • 1970-01-01
      • 2021-11-19
      • 2015-09-13
      相关资源
      最近更新 更多