change TypeInfo.GetCustomAttributes<BaseCommandModule>(false) != null, to (...).Length > 0

Created by: Eliemer

Summary

During CommandsNextEntension.RegisterCommands(), theres a check for IsModuleCandidateType(). In that check theres an "if" statement that checks for compiler generated attributes in the form of a null check. For the sake of interoperability with F# i suggest adding a check for Array.Length > 0, since F# types (classes) will never return a null value and thus always be flagged as Compiler generated classes.

With this issue, I can't use the CommandsNext package at all, as it will always cause an error on startup

Details

relevant piece of code is in:

relevant stacktrace:

ArgumentNullException: Type must be a class, which cannot be abstract or static. (Parameter 't')
   at DSharpPlus.CommandsNext.CommandsNextExtension.RegisterCommands(Type t)
   at DSharpPlus.CommandsNext.CommandsNextExtension.RegisterCommands[T]()
   at <StartupCode$DiscordBotFSharp>.$Core..cctor() in C:\Users\EliRodriguez\source\repos\DiscordBotFSharp\DiscordBotFSharp\Core.fs:line 79

my command class:

namespace Bot.Commands

open System.Threading.Tasks
open DSharpPlus.CommandsNext
open DSharpPlus.CommandsNext.Attributes
open DSharpPlus.Entities

type Commands = 
    inherit BaseCommandModule

    member private self.Ping(ctx : CommandContext) : Async<unit> = 
        async { 
            do! ctx.TriggerTypingAsync() 
                |> Async.AwaitTask

            let emoji = DiscordEmoji.FromName(ctx.Client, ":ping_pong:")

            do! ctx.RespondAsync(sprintf "%s Pong! Socket Latency: %ims" (emoji.ToString()) ctx.Client.Ping) 
                |> Async.AwaitTask 
                |> Async.Ignore
        }

    [<Command("ping"); Description("Responds with socket latency")>]
    member public self.PingAsync(ctx : CommandContext) : Task<unit> =
        self.Ping ctx |> Async.StartAsTask

my command register code:

// reads a json, custom type
let config = ConfigLoader.loadConfig()

// DiscordConfiguration object
let discordConfig = ConfigLoader.loadDiscordConfig(config)

// CommandsNextConfiguration object
let commandConfig = ConfigLoader.loadCommandConfig(config)
   
let discordClient = new DiscordClient(discordConfig)
let commands = discordClient.UseCommandsNext(commandConfig) 
commands.RegisterCommands<Commands>()

Suggested edit:

var compilerAttrs = ti.GetCustomAttribute<CompilerGeneratedAttribute>(false);
if (compilerAttrs != null && compilerAttrs.Length > 0)