diff --git a/Obsidian/Events/MinecraftEvent.cs b/Obsidian/Events/MinecraftEvent.cs deleted file mode 100644 index 05bcea273..000000000 --- a/Obsidian/Events/MinecraftEvent.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Internal; -using Microsoft.Extensions.Logging; -using Obsidian.Plugins; -using System.Diagnostics; - -namespace Obsidian.Events; -internal readonly struct MinecraftEvent -{ - public required Type EventType { get; init; } - - public required ILogger Logger { get; init; } - - public Type? ModuleType { get; init; } - - public required PluginContainer? PluginContainer { get; init; } - - public required Priority Priority { get; init; } - - public ObjectFactory? ModuleFactory { get; init; } - - public ObjectMethodExecutor? MethodExecutor { get; init; } - - public Delegate? MethodDelegate { get; init; } - - //TODO PARAM INJECTION - public async ValueTask Execute(IServiceProvider serviceProvider, params object[]? methodParams) - { - if (this.MethodExecutor != null) - { - var module = this.ModuleFactory!.Invoke(this.PluginContainer?.ServiceScope.ServiceProvider - ?? serviceProvider, null)//Will inject services through constructor - ?? throw new InvalidOperationException("Failed to initialize module from factory."); - - this.PluginContainer?.InjectServices(this.Logger, module); //inject through attribute - - if (this.MethodExecutor.MethodReturnType == typeof(ValueTask)) - { - await (ValueTask)this.MethodExecutor.Execute(module!, methodParams)!; - return; - } - else if (this.MethodExecutor.MethodReturnType == typeof(Task)) - { - await ((Task)this.MethodExecutor.Execute(module, methodParams)!).ConfigureAwait(false); - return; - } - - this.MethodExecutor.Execute(module, methodParams); - - return; - } - - if (this.MethodDelegate == null) - throw new UnreachableException(); - - if (this.MethodDelegate.Method.ReturnType == typeof(ValueTask)) - { - await (ValueTask)this.MethodDelegate.DynamicInvoke(methodParams)!; - return; - } - else if (this.MethodDelegate.Method.ReturnType == typeof(Task)) - { - await ((Task)this.MethodDelegate.DynamicInvoke(methodParams)!).ConfigureAwait(false); - return; - } - - this.MethodDelegate.DynamicInvoke(methodParams); - } -} diff --git a/Obsidian/Events/MinecraftEventExecutor.Delegate.cs b/Obsidian/Events/MinecraftEventExecutor.Delegate.cs new file mode 100644 index 000000000..40251a440 --- /dev/null +++ b/Obsidian/Events/MinecraftEventExecutor.Delegate.cs @@ -0,0 +1,42 @@ +using Microsoft.Extensions.Logging; +using Obsidian.Plugins; +using Obsidian.Utilities.Interfaces; +using System.Reflection; + +namespace Obsidian.Events; +internal readonly struct MinecraftEventDelegateExecutor : IEventExecutor +{ + public required Type EventType { get; init; } + + public required Priority Priority { get; init; } + + public required ILogger? Logger { get; init; } + + public PluginContainer? PluginContainer { get; init; } + + public required Delegate MethodDelegate { get; init; } + + public ParameterInfo[] GetParameters() => this.MethodDelegate.Method.GetParameters(); + + public IEnumerable GetCustomAttributes() where TAttribute : Attribute => + this.MethodDelegate.Method.GetCustomAttributes(); + + //TODO PARAM INJECTIONS + public async ValueTask Execute(IServiceProvider serviceProvider, params object[]? methodParams) + { + if (this.MethodDelegate.Method.ReturnType == typeof(ValueTask)) + { + await (ValueTask)this.MethodDelegate.DynamicInvoke(methodParams)!; + return; + } + else if (this.MethodDelegate.Method.ReturnType == typeof(Task)) + { + await ((Task)this.MethodDelegate.DynamicInvoke(methodParams)!).ConfigureAwait(false); + return; + } + + this.MethodDelegate.DynamicInvoke(methodParams); + } + + public bool MatchParams(object[] args) => throw new NotImplementedException(); +} diff --git a/Obsidian/Events/MinecraftEventExecutor.cs b/Obsidian/Events/MinecraftEventExecutor.cs new file mode 100644 index 000000000..dcb247b7c --- /dev/null +++ b/Obsidian/Events/MinecraftEventExecutor.cs @@ -0,0 +1,54 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Internal; +using Microsoft.Extensions.Logging; +using Obsidian.Plugins; +using Obsidian.Utilities.Interfaces; +using System.Diagnostics; +using System.Reflection; + +namespace Obsidian.Events; +internal readonly struct MinecraftEventExecutor : IEventExecutor +{ + public required Type EventType { get; init; } + + public required ILogger Logger { get; init; } + + public required Type ModuleType { get; init; } + + public required PluginContainer? PluginContainer { get; init; } + + public required Priority Priority { get; init; } + + public required ObjectFactory ModuleFactory { get; init; } + + public required ObjectMethodExecutor MethodExecutor { get; init; } + + //TODO PARAM INJECTION + public async ValueTask Execute(IServiceProvider serviceProvider, params object[]? methodParams) + { + var module = this.ModuleFactory!.Invoke(this.PluginContainer?.ServiceScope.ServiceProvider + ?? serviceProvider, null);//Will inject services through constructor + + this.PluginContainer?.InjectServices(this.Logger, module); //inject through attribute + + if (this.MethodExecutor.MethodReturnType == typeof(ValueTask)) + { + await (ValueTask)this.MethodExecutor.Execute(module, methodParams)!; + return; + } + else if (this.MethodExecutor.MethodReturnType == typeof(Task)) + { + await ((Task)this.MethodExecutor.Execute(module, methodParams)!).ConfigureAwait(false); + return; + } + + this.MethodExecutor.Execute(module, methodParams); + } + + public ParameterInfo[] GetParameters() => this.MethodExecutor.MethodParameters; + + public IEnumerable GetCustomAttributes() where TAttribute : Attribute => + this.MethodExecutor.MethodInfo.GetCustomAttributes(); + + public bool MatchParams(object[] args) => this.GetParameters().Length - 1 == args.Length; +} diff --git a/Obsidian/Services/EventDispatcher.cs b/Obsidian/Services/EventDispatcher.cs index 22aa49819..140ff0fd1 100644 --- a/Obsidian/Services/EventDispatcher.cs +++ b/Obsidian/Services/EventDispatcher.cs @@ -6,6 +6,7 @@ using Obsidian.Events; using Obsidian.Events.EventArgs; using Obsidian.Plugins; +using Obsidian.Utilities.Interfaces; using System.Collections.Frozen; using System.Reflection; using System.Runtime.CompilerServices; @@ -21,7 +22,7 @@ public sealed class EventDispatcher : IDisposable private readonly ILogger logger; private readonly IServiceProvider serviceProvider; - private readonly FrozenDictionary> registeredEvents; + private readonly FrozenDictionary> registeredEvents; private readonly FrozenDictionary eventNames; public EventDispatcher(ILogger logger, IServiceProvider serviceProvider) @@ -33,7 +34,7 @@ public EventDispatcher(ILogger logger, IServiceProvider service .ToList(); //Temp workaround until we decide to expose this event - var dict = new Dictionary>() + var dict = new Dictionary>() { { "QueuePacket", [] } }; @@ -73,7 +74,7 @@ public void RegisterEvents(PluginContainer? pluginContainer) where if (!this.registeredEvents.TryGetValue(this.eventNames[eventType], out var values)) continue; - values.Add(new() + values.Add(new MinecraftEventExecutor { EventType = eventType, ModuleFactory = ActivatorUtilities.CreateFactory(eventModule, []), @@ -93,7 +94,7 @@ public void RegisterEvent(PluginContainer pluginContainer, ValueTask if (!this.registeredEvents.TryGetValue(this.eventNames[typeof(TEventArgs)], out var values)) return; - values.Add(new() + values.Add(new MinecraftEventDelegateExecutor { EventType = typeof(TEventArgs), PluginContainer = pluginContainer, @@ -111,7 +112,7 @@ public void RegisterEvent(PluginContainer? pluginContainer, Delegate handler, Pr if (!this.registeredEvents.TryGetValue(this.eventNames[eventType], out var values)) return; - values.Add(new() + values.Add(new MinecraftEventDelegateExecutor { EventType = eventType, PluginContainer = pluginContainer, @@ -143,7 +144,7 @@ public void RegisterEvents(PluginContainer pluginContainer) if (!this.registeredEvents.TryGetValue(this.eventNames[eventType], out var values)) continue; - values.Add(new() + values.Add(new MinecraftEventExecutor { EventType = eventType, ModuleFactory = ActivatorUtilities.CreateFactory(eventModule, []), diff --git a/Obsidian/Utilities/Interfaces/IExecutor.cs b/Obsidian/Utilities/Interfaces/IExecutor.cs index 15ca52557..cbeff7546 100644 --- a/Obsidian/Utilities/Interfaces/IExecutor.cs +++ b/Obsidian/Utilities/Interfaces/IExecutor.cs @@ -21,3 +21,10 @@ public interface IExecutor public ValueTask Execute(IServiceProvider serviceProvider, TArg arg, params object[]? methodParams); } + +public interface IEventExecutor : IExecutor +{ + public Type EventType { get; init; } + + public Priority Priority { get; init; } +}