Files
Workspace/Assets/Modules/ShrinkCommand/Runtime/Routing/ShrinkCommandRegHelper.cs
T

117 lines
4.3 KiB
C#

#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace ShrinkCommand
{
public static class ShrinkCommandRegHelper
{
public static void RegisterStaticCommands(ShrinkCommandService service)
{
if (service == null)
throw new ArgumentNullException(nameof(service));
RegisterStaticCommandSubscriberTypes(service, ShrinkCommandGeneratedRegistry.GetStaticSubscriberTypes());
}
public static void RegisterCommands(ShrinkCommandService service, object? target)
{
if (service == null)
throw new ArgumentNullException(nameof(service));
RegisterCommandsInternal(service, target);
}
public static void RegisterStaticCommandSubscriberTypes(
ShrinkCommandService service,
IEnumerable<Type> subscriberTypes)
{
if (service == null)
throw new ArgumentNullException(nameof(service));
if (subscriberTypes == null)
throw new ArgumentNullException(nameof(subscriberTypes));
foreach (var type in subscriberTypes)
{
if (type == null || type.GetCustomAttribute<ShrinkCommandSubscriberAttribute>(false) == null)
continue;
ScanMethodsAndRegister(service, null, type,
type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
}
}
private static void RegisterCommandsInternal(ShrinkCommandService service, object? target)
{
if (target == null)
return;
var ownerType = target.GetType();
if (ownerType.GetCustomAttribute<ShrinkCommandSubscriberAttribute>(false) == null)
return;
ScanMethodsAndRegister(service, target, ownerType,
ownerType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
}
private static void ScanMethodsAndRegister(
ShrinkCommandService service,
object? target,
Type ownerType,
MethodInfo[] methods)
{
foreach (var method in methods)
{
if (target != null && method.IsStatic)
continue;
var attributes = method.GetCustomAttributes(typeof(ShrinkCommandAttribute), false)
.Cast<ShrinkCommandAttribute>()
.ToArray();
if (attributes.Length == 0)
continue;
foreach (var attribute in attributes)
{
try
{
service.RegisterCommand(new ShrinkCommandRegistration
{
Path = attribute.Path,
Aliases = attribute.Aliases ?? Array.Empty<string>(),
Description = attribute.Description,
Permission = attribute.Permission,
SourceKind = attribute.SourceKind,
Hidden = attribute.Hidden,
Handler = ShrinkCommandMethodAdapter.BuildHandler(target, method,
ParseArgumentNames(attribute.Path))
});
}
catch (Exception ex)
{
ShrinkCommandLogger.Warn(
$"[ShrinkCommand] Failed to register {ownerType.FullName}.{method.Name}: {ex.Message}");
}
}
}
}
private static string[] ParseArgumentNames(string path)
{
return path.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Where(token => token.Length >= 3 && token[0] == '<' && token[token.Length - 1] == '>')
.Select(token =>
{
var name = token.Substring(1, token.Length - 2).Trim();
if (name.EndsWith("...", StringComparison.Ordinal))
name = name.Substring(0, name.Length - 3).Trim();
return name;
})
.ToArray();
}
}
}