117 lines
4.3 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|