From 9f34f8f00f7ccc5221dc86cc46405b1faf00be31 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Thu, 1 Jul 2021 23:53:06 +0200 Subject: [PATCH] Don't load executor behaviors as a dep, but initialize after all services are loaded. Experimenting on services --- src/NadekoBot/Bot.cs | 15 +++-- src/NadekoBot/Services/CommandHandler.cs | 15 ++--- src/NadekoBot/Services/IBehaviourExecutor.cs | 3 + .../Services/Impl/BehaviorExecutor.cs | 32 +++++----- src/NadekoBot/_Extensions/Extensions.cs | 64 ------------------- 5 files changed, 35 insertions(+), 94 deletions(-) diff --git a/src/NadekoBot/Bot.cs b/src/NadekoBot/Bot.cs index 6f3f12df7..95c709ce1 100644 --- a/src/NadekoBot/Bot.cs +++ b/src/NadekoBot/Bot.cs @@ -21,9 +21,6 @@ using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Common.Configs; using NadekoBot.Db; using NadekoBot.Modules.Gambling.Services; -using NadekoBot.Modules.Administration.Services; -using NadekoBot.Modules.CustomReactions.Services; -using NadekoBot.Modules.Utility.Services; using Serilog; namespace NadekoBot @@ -132,8 +129,6 @@ namespace NadekoBot AllowAutoRedirect = false }); - svcs.LoadFrom(Assembly.GetAssembly(typeof(CommandHandler))); - if (Environment.GetEnvironmentVariable("NADEKOBOT_IS_COORDINATED") != "1") { svcs.AddSingleton(); @@ -144,6 +139,7 @@ namespace NadekoBot .AddSingleton(x => (IReadyExecutor)x.GetRequiredService()); } + // todo no public bot attribute svcs.Scan(scan => scan .FromAssemblyOf() .AddClasses(classes => classes.AssignableTo()) @@ -160,6 +156,12 @@ namespace NadekoBot .AsSelf() .AsImplementedInterfaces() .WithSingletonLifetime() + + // services + .AddClasses(classes => classes.AssignableTo()) + .AsImplementedInterfaces() + .AsSelf() + .WithSingletonLifetime() ); // svcs.AddSingleton(x => x.GetService()); @@ -168,7 +170,8 @@ namespace NadekoBot //initialize Services Services = svcs.BuildServiceProvider(); - var commandHandler = Services.GetService(); + var exec = Services.GetRequiredService(); + exec.Initialize(); if (Client.ShardId == 0) { diff --git a/src/NadekoBot/Services/CommandHandler.cs b/src/NadekoBot/Services/CommandHandler.cs index 8bea488b6..e84f7851b 100644 --- a/src/NadekoBot/Services/CommandHandler.cs +++ b/src/NadekoBot/Services/CommandHandler.cs @@ -3,7 +3,6 @@ using Discord.Commands; using Discord.Net; using Discord.WebSocket; using NadekoBot.Common.Collections; -using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Extensions; using System; using System.Collections.Concurrent; @@ -12,7 +11,6 @@ using System.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; using NadekoBot.Common.Configs; using NadekoBot.Db; using Serilog; @@ -28,9 +26,9 @@ namespace NadekoBot.Services private readonly BotConfigService _bss; private readonly Bot _bot; private readonly IBehaviourExecutor _behaviourExecutor; - private IServiceProvider _services; - - private ConcurrentDictionary _prefixes { get; } = new ConcurrentDictionary(); + private readonly IServiceProvider _services; + + private readonly ConcurrentDictionary _prefixes; public event Func CommandExecuted = delegate { return Task.CompletedTask; }; public event Func CommandErrored = delegate { return Task.CompletedTask; }; @@ -106,7 +104,8 @@ namespace NadekoBot.Services gc.Prefix = prefix; uow.SaveChanges(); } - _prefixes.AddOrUpdate(guild.Id, prefix, (key, old) => prefix); + + _prefixes[guild.Id] = prefix; return prefix; } @@ -179,8 +178,8 @@ namespace NadekoBot.Services "Message: {3}\n\t" + "Error: {4}", usrMsg.Author + " [" + usrMsg.Author.Id + "]", // {0} - (channel is null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1} - (channel is null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2} + channel is null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]", // {1} + channel is null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]", // {2} usrMsg.Content,// {3} errorMessage //exec.Result.ErrorReason // {4} diff --git a/src/NadekoBot/Services/IBehaviourExecutor.cs b/src/NadekoBot/Services/IBehaviourExecutor.cs index 96b179adf..f60d53530 100644 --- a/src/NadekoBot/Services/IBehaviourExecutor.cs +++ b/src/NadekoBot/Services/IBehaviourExecutor.cs @@ -2,6 +2,7 @@ using Discord; using Discord.Commands; using Discord.WebSocket; +using Microsoft.Extensions.DependencyInjection; namespace NadekoBot.Services { @@ -11,5 +12,7 @@ namespace NadekoBot.Services public Task RunInputTransformersAsync(SocketGuild guild, IUserMessage usrMsg); Task RunLateBlockersAsync(ICommandContext context, CommandInfo cmd); Task RunLateExecutorsAsync(SocketGuild guild, IUserMessage usrMsg); + + public void Initialize(); } } \ No newline at end of file diff --git a/src/NadekoBot/Services/Impl/BehaviorExecutor.cs b/src/NadekoBot/Services/Impl/BehaviorExecutor.cs index 9123836b1..a560a2fcf 100644 --- a/src/NadekoBot/Services/Impl/BehaviorExecutor.cs +++ b/src/NadekoBot/Services/Impl/BehaviorExecutor.cs @@ -7,29 +7,29 @@ using Discord.WebSocket; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Extensions; using Serilog; +using Microsoft.Extensions.DependencyInjection; namespace NadekoBot.Services { public sealed class BehaviorExecutor : IBehaviourExecutor { - private readonly DiscordSocketClient _client; - private readonly IEnumerable _lateExecutors; - private readonly IEnumerable _lateBlockers; - private readonly IEnumerable _earlyBehaviors; - private readonly IEnumerable _transformers; + private readonly IServiceProvider _services; + private IEnumerable _lateExecutors; + private IEnumerable _lateBlockers; + private IEnumerable _earlyBehaviors; + private IEnumerable _transformers; - public BehaviorExecutor( - DiscordSocketClient client, - IEnumerable lateExecutors, - IEnumerable lateBlockers, - IEnumerable earlyBehaviors, - IEnumerable transformers) + public BehaviorExecutor(IServiceProvider services) { - _client = client; - _lateExecutors = lateExecutors; - _lateBlockers = lateBlockers; - _earlyBehaviors = earlyBehaviors; - _transformers = transformers; + _services = services; + } + + public void Initialize() + { + _lateExecutors = _services.GetServices(); + _lateBlockers = _services.GetServices(); + _earlyBehaviors = _services.GetServices(); + _transformers = _services.GetServices(); } // todo early behaviors should print for themselves diff --git a/src/NadekoBot/_Extensions/Extensions.cs b/src/NadekoBot/_Extensions/Extensions.cs index 3a31280d1..79a382b8e 100644 --- a/src/NadekoBot/_Extensions/Extensions.cs +++ b/src/NadekoBot/_Extensions/Extensions.cs @@ -355,69 +355,5 @@ namespace NadekoBot.Extensions return msg.Content.Headers.ContentLength / 1.MB(); } - - - - public static IEnumerable LoadFrom(this IServiceCollection collection, Assembly assembly) - { - // list of all the types which are added with this method - List addedTypes = new List(); - - Type[] allTypes; - try - { - // first, get all types in te assembly - allTypes = assembly.GetTypes(); - } - catch (ReflectionTypeLoadException ex) - { - Log.Error(ex, "Error loading assembly types"); - return Enumerable.Empty(); - } - // all types which have INService implementation are services - // which are supposed to be loaded with this method - // ignore all interfaces and abstract classes - var services = new Queue(allTypes - .Where(x => x.GetInterfaces().Contains(typeof(INService)) - && !x.GetTypeInfo().IsInterface && !x.GetTypeInfo().IsAbstract -#if GLOBAL_NADEKO - && x.GetTypeInfo().GetCustomAttribute() is null -#endif - ) - .ToArray()); - - // we will just return those types when we're done instantiating them - addedTypes.AddRange(services); - - // get all interfaces which inherit from INService - // as we need to also add a service for each one of interfaces - // so that DI works for them too - var interfaces = new HashSet(allTypes - .Where(x => x.GetInterfaces().Contains(typeof(INService)) - && x.GetTypeInfo().IsInterface)); - - // keep instantiating until we've instantiated them all - while (services.Count > 0) - { - var serviceType = services.Dequeue(); //get a type i need to add - - if (collection.FirstOrDefault(x => x.ServiceType == serviceType) != null) // if that type is already added, skip - continue; - - //also add the same type - var interfaceType = interfaces.FirstOrDefault(x => serviceType.GetInterfaces().Contains(x)); - if (interfaceType != null) - { - addedTypes.Add(interfaceType); - collection.AddSingleton(interfaceType, serviceType); - } - else - { - collection.AddSingleton(serviceType, serviceType); - } - } - - return addedTypes; - } } }