System.StackOverflowException 在 C# discord 机器人中

System.StackOverflowException in C# discord bot

我正在 Discord .NET 0.9 中编写一个 discord 机器人,当我尝试 运行 时出现堆栈溢出错误。当我在 Functions.cs

中创建 Program.cs 的实例时出现问题

我的Program.cs:

using System;
using System.Linq;
using Discord;
using Discord.Commands;
using System.IO;
using fatobg;


namespace fatobg
{
    class Program
    {
        CommandManager cm = new CommandManager();
        public static Program _instance = new Program();

        static void Main(string[] args)
        {
            new Program().Start();
        }

        public DiscordClient _client;



        public void Start()
        {
            Console.Title = "Matchmaking Discord BOT";

            _client = new DiscordClient(x =>
            {
                x.AppName = "Gerry";
                x.AppUrl = "www.google.com";
                x.LogLevel = LogSeverity.Info;
                x.LogHandler = Log;
            });


            _client.UsingCommands(x =>
            {
                x.PrefixChar = '?';
                x.AllowMentionPrefix = true;
                x.HelpMode = HelpMode.Public;
            });

            var token = "Changed";
            cm.Commands(_client);
            onJoin();

            _client.ExecuteAndWait(async () =>
            {
                await _client.Connect(token, TokenType.Bot);
                setGame(_client, "?help");
            });

        }
        public void setGame(DiscordClient _client, string game)
        {
            _client.SetGame(game);
        }
        public void onJoin()
        {
            _client.UserJoined += async (s, e) =>
            {
                await e.Server.GetChannel(318558393759694849).SendMessage($":loudspeaker: | Everyone welcome {e.User.Mention} to the server!");
            };
        }

        public void Log(Object sender, LogMessageEventArgs e)
        {
            Console.WriteLine($"[{e.Severity}] [{e.Source}] {e.Message}");
        }




    }

}

我的CommandManager.cs:

using System;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading.Tasks;
using Discord;
using System.Net.Http;
using Discord.Commands;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using System.IO;
using System.Threading;
using MySql.Data;
using MySql.Data.MySqlClient;

namespace fatobg
{
    class CommandManager
    {
        public static CommandManager _instance = new CommandManager();

        Functions function = new Functions();

        public void Commands(DiscordClient _client)
        {
            var cService = _client.GetService<CommandService>();

            cService.CreateCommand("say")
               .Description("returns commands")
               .Parameter("message", ParameterType.Unparsed)
               .Do(async (e) =>
               {
                   Message[] messageToDelete;
                   int deleteNumber = 1;
                   messageToDelete = await e.Channel.DownloadMessages(deleteNumber);
                   await e.Channel.DeleteMessages(messageToDelete);

                   var toReturn = $":envelope: | {e.GetArg("message")}";
                   await e.Channel.SendMessage(toReturn);
                   Console.WriteLine(toReturn);
               });

            cService.CreateCommand("updatedb")
                .Description("updates database")
                .Do(async (e) =>
                {
                        Message[] messageToDelete; //deletes command
                        int deleteNumber = 1;
                        messageToDelete = await e.Channel.DownloadMessages(deleteNumber);
                        await e.Channel.DeleteMessages(messageToDelete);
                        try
                        {
                            if (e.User.ServerPermissions.Administrator)
                        { 
                                foreach (User user in e.Server.Users)
                                {
                                     if(!user.IsBot)
                                        function.UpdateDB(user);
                                }
                                var toReturn = $":white_check_mark: | Done updateing the database. {e.User.Mention}";
                                await e.Channel.SendMessage(toReturn);
                                Console.WriteLine(toReturn);
                            }
                            else
                            {
                                var toReturn = $":exclamation: | Get out of here {e.User.Mention} you have no power over me!";
                                await e.Channel.SendMessage(toReturn);
                                Console.WriteLine(toReturn);
                            }
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Error: " + ex);
                        }
                });

            cService.CreateCommand("duo")
               .Description("returns commands")
               .Do(async (e) =>
               {
                   Message[] messageToDelete;
                   int deleteNumber = 1;
                   messageToDelete = await e.Channel.DownloadMessages(deleteNumber);
                   await e.Channel.DeleteMessages(messageToDelete);

               });

            cService.CreateCommand("yamikage")
               .Description("Animated gingy")
               .Do(async (e) =>
               {
                   Message[] messageToDelete;
                   int deleteNumber = 1;
                   messageToDelete = await e.Channel.DownloadMessages(deleteNumber);
                   await e.Channel.DeleteMessages(messageToDelete);

                   await e.Channel.SendFile("Gifs/gingy.gif");
                   Console.WriteLine("Send epic gingy meme");
               });

        }

    }

}

我的Functions.cs:

using Discord;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace fatobg
{
    class Functions
    {
        Program main = new Program();

        public void UpdateDB(User user)
        {
            if (File.Exists(@"D:\Databases\DiscordUsers\" + user.Id + ".duser"))
            {
                System.IO.File.Delete(@"D:\Databases\DiscordUsers\" + user.Id + ".duser");
                string[] Data = { user.Name, Roles(user) };
                System.IO.File.WriteAllLines(@"D:\Databases\DiscordUsers\" + user.Id + ".duser", Data);
            }
            else
            {
                string[] Data = { user.Name, Roles(user) };
                System.IO.File.WriteAllLines(@"D:\Databases\DiscordUsers\" + user.Id + ".duser", Data);
            }
        }

        public string Roles(User user)
        {
            string toreturn = string.Empty;
            foreach (Role role in user.Roles)
            {
                if (role.Name!="Admin"||role.Name!="Mod"||role.Name!="@everyone")
                {
                    toreturn += role.Name + "|";
                }
            }
            return toreturn;
        }

        public string GetUsername(string uid)
        {
            if (File.Exists(@"D:\Databases\DiscordUsers\" + uid + ".duser"))
            {
                string[] Data = File.ReadAllLines(@"D:\Databases\DiscordUsers\" + uid + ".duser");
                return Data[0];
            }
            else
            {
                return null;
            }
        }

        public void AddToQueue(User user)
        {
            List<User> NA = new List<User>();
            List<User> EU = new List<User>();
            List<User> OC = new List<User>();
            List<User> AS = new List<User>();
            List<User> SA = new List<User>();

            Server server = main._client.FindServers("Find A Team On Battlegrounds (Bot Testing)").FirstOrDefault();
            User usr = server.FindUsers(user.Name).FirstOrDefault();

            if (File.Exists(@"D:\Databases\Duo.queue"))
            {
                string[] UData = System.IO.File.ReadAllLines(@"D:\Databases\Duo.queue");
                System.IO.File.Delete(@"D:\Databases\Duo.queue");
                foreach(String uid in UData)
                {
                    User tempuser = user.Server.FindUsers(GetUsername(uid)).FirstOrDefault();
                    List<Role> roles = tempuser.Roles.ToList();
                    foreach(Role role in roles)
                    {

                        if (role.Name == "[NA]")
                            NA.Add(tempuser);
                        else if (role.Name == "[EU]")
                            EU.Add(tempuser);
                        else if (role.Name == "[OC]")
                            OC.Add(tempuser);
                        else if (role.Name == "[AS]")
                            AS.Add(tempuser);
                        else if (role.Name == "[SA]")
                            SA.Add(tempuser);
                    }
                }

                List<Role> uroles = usr.Roles.ToList();
                foreach (Role role in uroles)
                {
                    if (role.Name == "[NA]")
                        NA.Add(usr);
                    else if (role.Name == "[EU]")
                        EU.Add(usr);
                    else if (role.Name == "[OC]")
                        OC.Add(usr);
                    else if (role.Name == "[AS]")
                        AS.Add(usr);
                    else if (role.Name == "[SA]")
                        SA.Add(usr);
                }

                File.WriteAllLines(@"D:\Databases\Duo.queue", UData);
                File.AppendAllText(@"D:\Databases\Duo.queue", usr.Id.ToString() + Environment.NewLine);

                if (NA.Count == 2)
                {
                    server.GetChannel(319281246746312714).SendMessage($":exclamation: | A new team has been found for NA servers. {NA[0].Mention} and {NA[1].Mention} prepare to fight.");
                    string[] Data = System.IO.File.ReadAllLines(@"D:\Databases\Duo.queue");
                    System.IO.File.Delete(@"D:\Databases\Duo.queue");
                    foreach (String id in Data)
                    {
                        if(id!=NA[0].Id.ToString()&&id!=NA[1].Id.ToString())
                            File.AppendAllText(@"D:\Databases\Duo.queue", id + Environment.NewLine);
                    }
                    NA.Clear();
                }
                else if (EU.Count == 2){
                    server.GetChannel(319281246746312714).SendMessage($":exclamation: | A new team has been found for EU servers. {EU[0].Mention} and {EU[1].Mention} prepare to fight.");
                    string[] Data = System.IO.File.ReadAllLines(@"D:\Databases\Duo.queue");
                    System.IO.File.Delete(@"D:\Databases\Duo.queue");
                    foreach (String id in Data)
                    {
                        if (id!=EU[0].Id.ToString()&&id!=EU[1].Id.ToString())
                            File.AppendAllText(@"D:\Databases\Duo.queue", id + Environment.NewLine);
                    }
                    EU.Clear();
                }
                else if (OC.Count == 2)
                {
                    server.GetChannel(319281246746312714).SendMessage($":exclamation: | A new team has been found for OC servers. {OC[0].Mention} and {OC[1].Mention} prepare to fight.");
                    string[] Data = System.IO.File.ReadAllLines(@"D:\Databases\Duo.queue");
                    System.IO.File.Delete(@"D:\Databases\Duo.queue");
                    foreach (String id in Data)
                    {
                        if (id!=OC[0].Id.ToString()&&id!=OC[1].Id.ToString())
                            File.AppendAllText(@"D:\Databases\Duo.queue", id + Environment.NewLine);
                    }
                    OC.Clear();
                }
                else if (AS.Count == 2)
                {
                    server.GetChannel(319281246746312714).SendMessage($":exclamation: | A new team has been found for AS servers. {AS[0].Mention} and {AS[1].Mention} prepare to fight.");
                    string[] Data = System.IO.File.ReadAllLines(@"D:\Databases\Duo.queue");
                    System.IO.File.Delete(@"D:\Databases\Duo.queue");
                    foreach (String id in Data)
                    {
                        if (id != AS[0].Id.ToString() && id != AS[1].Id.ToString())
                            File.AppendAllText(@"D:\Databases\Duo.queue", id + Environment.NewLine);
                    }
                    AS.Clear();
                }
                else if (SA.Count == 2)
                {
                    server.GetChannel(319281246746312714).SendMessage($":exclamation: | A new team has been found for SA servers. {SA[0].Mention} and {SA[1].Mention} prepare to fight.");
                    string[] Data = System.IO.File.ReadAllLines(@"D:\Databases\Duo.queue");
                    System.IO.File.Delete(@"D:\Databases\Duo.queue");
                    foreach (String id in Data)
                    {
                        if (id != SA[0].Id.ToString()&&id!=SA[1].Id.ToString())
                            File.AppendAllText(@"D:\Databases\Duo.queue", id + Environment.NewLine);
                    }
                    SA.Clear();
                }

            }
            else
            {
                File.AppendAllText(@"D:\Databases\Duo.queue", usr.Id.ToString() + Environment.NewLine);
            }
        }

    }
}

事情是这样的:

  1. 实例化Program;
  2. Program 实例化 CommandManager;
  3. CommandManager 实例化 Functions;
  4. Functions 实例化 Program;
  5. Return 到 1.

你应该做什么:

Program实例传递给CommandManagerFunctions。这样,你就没有循环引用了。

例如,您的 Functions class 应该以此开头:

class Functions
{
    Program main;

    public Functions(Program p)
    {
        this.main = p;
    }

还有你的CommandManager

class CommandManager
{
    Program main;
    Functions function;

    public CommandManager(Program p)
    {
        this.main = p;
        this.function = new Function(p);
    }