using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace axXez.TS3.Bot { /// Metadata descriptor for a module type — name, display name, description, namespace, and the CLR type itself. public class ModuleType { /// Short name of the module (class name). public string Name => Type.Name; /// Fully qualified name of the module (namespace + class name), e.g. "axXez.Greetings". public string FullName => $"{Namespace}.{Name}"; /// Human-readable display name. Returns if set, otherwise falls back to . public string DisplayName => Attribute != null && !string.IsNullOrWhiteSpace(Attribute.DisplayName) ? Attribute.DisplayName : Name; /// Short description of the module. Returns if set, otherwise empty. public string Description => Attribute != null && !string.IsNullOrWhiteSpace(Attribute.Description) ? Attribute.Description : string.Empty; /// Namespace prefix. Returns if set, otherwise the type's CLR namespace. public string Namespace => Attribute != null && !string.IsNullOrWhiteSpace(Attribute.Namespace) ? Attribute.Namespace : Type.Namespace; /// The underlying CLR type of the module. public Type Type { get; private set; } /// The applied to the module class, or null if none is present. public ModuleAttribute Attribute { get; private set; } /// Returns true if this module is compatible with the given server version. public bool IsCompatibleWith(ServerVersion version) { var compat = Attribute?.Compatibility ?? ModuleCompatibility.Any; return version switch { ServerVersion.TS3 => compat.HasFlag(ModuleCompatibility.TS3), ServerVersion.TS6 => compat.HasFlag(ModuleCompatibility.TS6), _ => compat.HasFlag(ModuleCompatibility.Unknown) }; } internal IReadOnlyList<(MethodInfo Method, CommandAttribute Attr)> CommandMethods { get; private set; } private ModuleType(Type type) { Type = type; Attribute = type.GetCustomAttribute(false); CommandMethods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) .Select(m => (Method: m, Attr: m.GetCustomAttribute())) .Where(x => x.Attr != null) .ToList(); } internal static ModuleType FromType(Type type) => new ModuleType(type); internal static ModuleType FromType() where T : Module => new ModuleType(typeof(T)); internal static IEnumerable FromAssembly(Assembly assembly) => assembly.GetTypes().Where(x => typeof(Module).IsAssignableFrom(x) && x.IsAbstract == false).Select(FromType); /// public override string ToString() => $"{Name} ({Type.FullName})"; /// public override int GetHashCode() => Type.GUID.GetHashCode(); /// public override bool Equals(object obj) => typeof(ModuleType).IsAssignableFrom(obj.GetType()) && (obj as ModuleType).Type.GUID.Equals(Type.GUID); } }