diff --git a/DisCatSharp/Clients/DiscordClient.InteractionEventHandlers.cs b/DisCatSharp/Clients/DiscordClient.InteractionEventHandlers.cs
index eb8a5c580..497a1c603 100644
--- a/DisCatSharp/Clients/DiscordClient.InteractionEventHandlers.cs
+++ b/DisCatSharp/Clients/DiscordClient.InteractionEventHandlers.cs
@@ -1,222 +1,226 @@
// This file is part of the DisCatSharp project, based off DSharpPlus.
//
// Copyright (c) 2021-2023 AITSYS
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
namespace DisCatSharp;
///
/// A Discord API wrapper.
///
public sealed partial class DiscordClient
{
- private readonly Dictionary<(object?, Type, bool), List<(EventInfo, Delegate)[]>> _registrationInteractionToDelegate = new();
+ private readonly Dictionary<(object?, Type, bool), List<(EventInfo, Delegate, bool)[]>> _registrationInteractionToDelegate = new();
private readonly Dictionary> _typeInteractionToAnonymousHandlers = new();
///
/// Registers all methods annotated with from the given object.
///
/// The event handler object.
/// Whether to consider static methods.
public void RegisterInteractionHandler(object handler, bool registerStatic = false)
=> this.RegisterInteractionHandlerImpl(handler, handler.GetType(), registerStatic);
///
/// Registers all static methods annotated with from the given type.
///
/// The static event handler type.
public void RegisterStaticInteractionHandler(Type t)
=> this.RegisterInteractionHandlerImpl(null, t);
///
/// .
///
/// Type to register.
public void RegisterStaticInteractionHandler()
=> this.RegisterStaticInteractionHandler(typeof(T));
///
/// If abstract, registers all static methods of the type.
/// If non-abstract, tries to instantiate it, optionally using the provided
/// and registers all instance and static methods.
///
/// Type to register.
public void RegisterInteractionHandler(Type type)
{
if (type.IsAbstract)
this.RegisterStaticInteractionHandler(type);
else
{
var anon = ActivatorUtilities.CreateInstance(this.Configuration.ServiceProvider, type);
this._typeInteractionToAnonymousHandlers[type] = this._typeInteractionToAnonymousHandlers.TryGetValue(type, out var anonObjs) ? anonObjs : (anonObjs = new());
anonObjs.Add(anon);
this.RegisterInteractionHandlerImpl(anon, type);
}
}
///
/// .
///
/// Type to register.
public void RegisterInteractionHandler()
=> this.RegisterInteractionHandler(typeof(T));
///
/// Registers all types associated with the provided assembly that have the attribute.
///
/// The assembly from which to get the types.
public void RegisterInteractionHandlers(Assembly assembly)
{
foreach (var t in GetInteractionHandlersFromAssembly(assembly))
this.RegisterInteractionHandler(t);
}
///
/// Perfectly mirrors .
///
/// The event handler object.
/// Whether it considered static methods.
public void UnregisterInteractionHandler(object handler, bool wasRegisteredWithStatic = false)
=> this.UnregisterInteractionHandlerImpl(handler, handler.GetType(), wasRegisteredWithStatic);
///
/// Perfectly mirrors .
///
/// Type to unregister.
public void UnregisterStaticInteractionHandler(Type t)
=> this.UnregisterInteractionHandlerImpl(null, t);
///
/// Perfectly mirrors .
///
/// Type to unregister.
public void UnregisterStaticInteractionHandler()
=> this.UnregisterInteractionHandler(typeof(T));
///
/// Perfectly mirrors .
///
/// Type to unregister.
public void UnregisterInteractionHandler(Type t)
{
if (t.IsAbstract)
this.UnregisterStaticInteractionHandler(t);
else
{
if (!this._typeInteractionToAnonymousHandlers.TryGetValue(t, out var anonObjs) || anonObjs.Count == 0)
return;
var anon = anonObjs[0];
anonObjs.RemoveAt(0);
if (anonObjs.Count == 0)
this._typeInteractionToAnonymousHandlers.Remove(t);
this.UnregisterInteractionHandlerImpl(anon, t);
}
}
///
/// Perfectly mirrors .
///
/// The type to unregister
public void UnregisterInteractionHandler()
=> this.UnregisterInteractionHandler(typeof(T));
///
/// Perfectly mirrors .
///
/// The assembly to unregister.
public void UnregisterInteractionHandlers(Assembly assembly)
{
foreach (var t in GetInteractionHandlersFromAssembly(assembly))
this.UnregisterInteractionHandler(t);
}
///
/// Gets the event handlers from the assembly.
///
/// The assembly to get the event handlers from.
private static IEnumerable GetInteractionHandlersFromAssembly(Assembly assembly)
=> assembly.GetTypes().Where(t => t.GetCustomAttribute() is not null);
///
/// Unregisters event handler implementations.
///
/// The event handler object.
/// The type.
/// Whether it considereded static methods.
private void UnregisterInteractionHandlerImpl(object? handler, Type type, bool wasRegisteredWithStatic = true)
{
if (!this._registrationInteractionToDelegate.TryGetValue((handler, type, wasRegisteredWithStatic), out var delegateLists) || delegateLists.Count == 0)
return;
- foreach (var (evnt, dlgt) in delegateLists[0])
+ foreach (var (evnt, dlgt, prv) in delegateLists[0])
evnt.RemoveEventHandler(this, dlgt);
delegateLists.RemoveAt(0);
if (delegateLists.Count == 0)
this._registrationInteractionToDelegate.Remove((handler, type, wasRegisteredWithStatic));
}
///
/// Rregisters event handler implementations.
///
/// The event handler object.
/// The type.
/// Whether to consider static methods.
private void RegisterInteractionHandlerImpl(object? handler, Type type, bool registerStatic = true)
{
- /*var delegates = (
+ var delegates = (
from method in type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
- let attribute = method.GetCustomAttribute()
+ let attribute = method.GetCustomAttribute()
where attribute is not null && ((registerStatic && method.IsStatic) || handler is not null)
- let eventName = attribute.EventName ?? method.Name
+ let eventName = attribute.EventName
let eventInfo = this.GetType().GetEvent(eventName)
?? throw new ArgumentException($"Tried to register handler to non-existent event \"{eventName}\"")
- let eventHandlerType = eventInfo.InteractionHandlerType
+ let eventHandlerType = eventInfo.EventHandlerType
+ let prefixed = attribute.IsPrefixed
let dlgt = (method.IsStatic
? Delegate.CreateDelegate(eventHandlerType, method, false)
: Delegate.CreateDelegate(eventHandlerType, handler, method, false))
?? throw new ArgumentException($"Method \"{method}\" does not adhere to event specification \"{eventHandlerType}\"")
- select (eventInfo, dlgt)
+ select (eventInfo, dlgt, prefixed)
).ToArray();
this._registrationInteractionToDelegate[(handler, type, registerStatic)] = this._registrationInteractionToDelegate.TryGetValue((handler, type, registerStatic), out var delList) ? delList : (delList = new());
delList.Add(delegates);
- foreach (var (evnt, dlgt) in delegates)
- evnt.AddEventHandler(this, dlgt);*/
+ foreach (var (evnt, dlgt, prv) in delegates)
+ if (!prv)
+ evnt.AddEventHandler(this, dlgt);
+ else
+ evnt.AddEventHandler(this, dlgt);
}
}