mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 17:28:27 -04:00
Don't load executor behaviors as a dep, but initialize after all services are loaded. Experimenting on services
This commit is contained in:
@@ -21,9 +21,6 @@ using NadekoBot.Common.ModuleBehaviors;
|
|||||||
using NadekoBot.Common.Configs;
|
using NadekoBot.Common.Configs;
|
||||||
using NadekoBot.Db;
|
using NadekoBot.Db;
|
||||||
using NadekoBot.Modules.Gambling.Services;
|
using NadekoBot.Modules.Gambling.Services;
|
||||||
using NadekoBot.Modules.Administration.Services;
|
|
||||||
using NadekoBot.Modules.CustomReactions.Services;
|
|
||||||
using NadekoBot.Modules.Utility.Services;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace NadekoBot
|
namespace NadekoBot
|
||||||
@@ -132,8 +129,6 @@ namespace NadekoBot
|
|||||||
AllowAutoRedirect = false
|
AllowAutoRedirect = false
|
||||||
});
|
});
|
||||||
|
|
||||||
svcs.LoadFrom(Assembly.GetAssembly(typeof(CommandHandler)));
|
|
||||||
|
|
||||||
if (Environment.GetEnvironmentVariable("NADEKOBOT_IS_COORDINATED") != "1")
|
if (Environment.GetEnvironmentVariable("NADEKOBOT_IS_COORDINATED") != "1")
|
||||||
{
|
{
|
||||||
svcs.AddSingleton<ICoordinator, SingleProcessCoordinator>();
|
svcs.AddSingleton<ICoordinator, SingleProcessCoordinator>();
|
||||||
@@ -144,6 +139,7 @@ namespace NadekoBot
|
|||||||
.AddSingleton<IReadyExecutor>(x => (IReadyExecutor)x.GetRequiredService<ICoordinator>());
|
.AddSingleton<IReadyExecutor>(x => (IReadyExecutor)x.GetRequiredService<ICoordinator>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo no public bot attribute
|
||||||
svcs.Scan(scan => scan
|
svcs.Scan(scan => scan
|
||||||
.FromAssemblyOf<IReadyExecutor>()
|
.FromAssemblyOf<IReadyExecutor>()
|
||||||
.AddClasses(classes => classes.AssignableTo<IReadyExecutor>())
|
.AddClasses(classes => classes.AssignableTo<IReadyExecutor>())
|
||||||
@@ -160,6 +156,12 @@ namespace NadekoBot
|
|||||||
.AsSelf()
|
.AsSelf()
|
||||||
.AsImplementedInterfaces()
|
.AsImplementedInterfaces()
|
||||||
.WithSingletonLifetime()
|
.WithSingletonLifetime()
|
||||||
|
|
||||||
|
// services
|
||||||
|
.AddClasses(classes => classes.AssignableTo<INService>())
|
||||||
|
.AsImplementedInterfaces()
|
||||||
|
.AsSelf()
|
||||||
|
.WithSingletonLifetime()
|
||||||
);
|
);
|
||||||
|
|
||||||
// svcs.AddSingleton<IReadyExecutor>(x => x.GetService<SelfService>());
|
// svcs.AddSingleton<IReadyExecutor>(x => x.GetService<SelfService>());
|
||||||
@@ -168,7 +170,8 @@ namespace NadekoBot
|
|||||||
|
|
||||||
//initialize Services
|
//initialize Services
|
||||||
Services = svcs.BuildServiceProvider();
|
Services = svcs.BuildServiceProvider();
|
||||||
var commandHandler = Services.GetService<CommandHandler>();
|
var exec = Services.GetRequiredService<IBehaviourExecutor>();
|
||||||
|
exec.Initialize();
|
||||||
|
|
||||||
if (Client.ShardId == 0)
|
if (Client.ShardId == 0)
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,6 @@ using Discord.Commands;
|
|||||||
using Discord.Net;
|
using Discord.Net;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Common.Collections;
|
using NadekoBot.Common.Collections;
|
||||||
using NadekoBot.Common.ModuleBehaviors;
|
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@@ -12,7 +11,6 @@ using System.Collections.Immutable;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using NadekoBot.Common.Configs;
|
using NadekoBot.Common.Configs;
|
||||||
using NadekoBot.Db;
|
using NadekoBot.Db;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
@@ -28,9 +26,9 @@ namespace NadekoBot.Services
|
|||||||
private readonly BotConfigService _bss;
|
private readonly BotConfigService _bss;
|
||||||
private readonly Bot _bot;
|
private readonly Bot _bot;
|
||||||
private readonly IBehaviourExecutor _behaviourExecutor;
|
private readonly IBehaviourExecutor _behaviourExecutor;
|
||||||
private IServiceProvider _services;
|
private readonly IServiceProvider _services;
|
||||||
|
|
||||||
private ConcurrentDictionary<ulong, string> _prefixes { get; } = new ConcurrentDictionary<ulong, string>();
|
private readonly ConcurrentDictionary<ulong, string> _prefixes;
|
||||||
|
|
||||||
public event Func<IUserMessage, CommandInfo, Task> CommandExecuted = delegate { return Task.CompletedTask; };
|
public event Func<IUserMessage, CommandInfo, Task> CommandExecuted = delegate { return Task.CompletedTask; };
|
||||||
public event Func<CommandInfo, ITextChannel, string, Task> CommandErrored = delegate { return Task.CompletedTask; };
|
public event Func<CommandInfo, ITextChannel, string, Task> CommandErrored = delegate { return Task.CompletedTask; };
|
||||||
@@ -106,7 +104,8 @@ namespace NadekoBot.Services
|
|||||||
gc.Prefix = prefix;
|
gc.Prefix = prefix;
|
||||||
uow.SaveChanges();
|
uow.SaveChanges();
|
||||||
}
|
}
|
||||||
_prefixes.AddOrUpdate(guild.Id, prefix, (key, old) => prefix);
|
|
||||||
|
_prefixes[guild.Id] = prefix;
|
||||||
|
|
||||||
return prefix;
|
return prefix;
|
||||||
}
|
}
|
||||||
@@ -179,8 +178,8 @@ namespace NadekoBot.Services
|
|||||||
"Message: {3}\n\t" +
|
"Message: {3}\n\t" +
|
||||||
"Error: {4}",
|
"Error: {4}",
|
||||||
usrMsg.Author + " [" + usrMsg.Author.Id + "]", // {0}
|
usrMsg.Author + " [" + usrMsg.Author.Id + "]", // {0}
|
||||||
(channel is null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
|
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.Name + " [" + channel.Id + "]", // {2}
|
||||||
usrMsg.Content,// {3}
|
usrMsg.Content,// {3}
|
||||||
errorMessage
|
errorMessage
|
||||||
//exec.Result.ErrorReason // {4}
|
//exec.Result.ErrorReason // {4}
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace NadekoBot.Services
|
namespace NadekoBot.Services
|
||||||
{
|
{
|
||||||
@@ -11,5 +12,7 @@ namespace NadekoBot.Services
|
|||||||
public Task<string> RunInputTransformersAsync(SocketGuild guild, IUserMessage usrMsg);
|
public Task<string> RunInputTransformersAsync(SocketGuild guild, IUserMessage usrMsg);
|
||||||
Task<bool> RunLateBlockersAsync(ICommandContext context, CommandInfo cmd);
|
Task<bool> RunLateBlockersAsync(ICommandContext context, CommandInfo cmd);
|
||||||
Task RunLateExecutorsAsync(SocketGuild guild, IUserMessage usrMsg);
|
Task RunLateExecutorsAsync(SocketGuild guild, IUserMessage usrMsg);
|
||||||
|
|
||||||
|
public void Initialize();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -7,29 +7,29 @@ using Discord.WebSocket;
|
|||||||
using NadekoBot.Common.ModuleBehaviors;
|
using NadekoBot.Common.ModuleBehaviors;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace NadekoBot.Services
|
namespace NadekoBot.Services
|
||||||
{
|
{
|
||||||
public sealed class BehaviorExecutor : IBehaviourExecutor
|
public sealed class BehaviorExecutor : IBehaviourExecutor
|
||||||
{
|
{
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly IServiceProvider _services;
|
||||||
private readonly IEnumerable<ILateExecutor> _lateExecutors;
|
private IEnumerable<ILateExecutor> _lateExecutors;
|
||||||
private readonly IEnumerable<ILateBlocker> _lateBlockers;
|
private IEnumerable<ILateBlocker> _lateBlockers;
|
||||||
private readonly IEnumerable<IEarlyBehavior> _earlyBehaviors;
|
private IEnumerable<IEarlyBehavior> _earlyBehaviors;
|
||||||
private readonly IEnumerable<IInputTransformer> _transformers;
|
private IEnumerable<IInputTransformer> _transformers;
|
||||||
|
|
||||||
public BehaviorExecutor(
|
public BehaviorExecutor(IServiceProvider services)
|
||||||
DiscordSocketClient client,
|
|
||||||
IEnumerable<ILateExecutor> lateExecutors,
|
|
||||||
IEnumerable<ILateBlocker> lateBlockers,
|
|
||||||
IEnumerable<IEarlyBehavior> earlyBehaviors,
|
|
||||||
IEnumerable<IInputTransformer> transformers)
|
|
||||||
{
|
{
|
||||||
_client = client;
|
_services = services;
|
||||||
_lateExecutors = lateExecutors;
|
}
|
||||||
_lateBlockers = lateBlockers;
|
|
||||||
_earlyBehaviors = earlyBehaviors;
|
public void Initialize()
|
||||||
_transformers = transformers;
|
{
|
||||||
|
_lateExecutors = _services.GetServices<ILateExecutor>();
|
||||||
|
_lateBlockers = _services.GetServices<ILateBlocker>();
|
||||||
|
_earlyBehaviors = _services.GetServices<IEarlyBehavior>();
|
||||||
|
_transformers = _services.GetServices<IInputTransformer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo early behaviors should print for themselves
|
// todo early behaviors should print for themselves
|
||||||
|
@@ -355,69 +355,5 @@ namespace NadekoBot.Extensions
|
|||||||
|
|
||||||
return msg.Content.Headers.ContentLength / 1.MB();
|
return msg.Content.Headers.ContentLength / 1.MB();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static IEnumerable<Type> LoadFrom(this IServiceCollection collection, Assembly assembly)
|
|
||||||
{
|
|
||||||
// list of all the types which are added with this method
|
|
||||||
List<Type> addedTypes = new List<Type>();
|
|
||||||
|
|
||||||
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<Type>();
|
|
||||||
}
|
|
||||||
// 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<Type>(allTypes
|
|
||||||
.Where(x => x.GetInterfaces().Contains(typeof(INService))
|
|
||||||
&& !x.GetTypeInfo().IsInterface && !x.GetTypeInfo().IsAbstract
|
|
||||||
#if GLOBAL_NADEKO
|
|
||||||
&& x.GetTypeInfo().GetCustomAttribute<NoPublicBotAttribute>() 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<Type>(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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user