using CommonLang.Property; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; namespace CommonServer.Command { public abstract class AbstractCommand { public abstract string Key { get; } public abstract void DoCommand(string arg, TextWriter output); public virtual string Help { get { DescAttribute desc = PropertyUtil.GetAttribute<DescAttribute>(GetType()); if (desc != null) { return (desc.Desc); } return GetType().Name; } } private static Regex reg = new Regex(@"\s+"); public static string[] ToArgs(string arg) { return reg.Split(arg); } } public class CommandList<T> where T : AbstractCommand { private SortedDictionary<string, T> cmd_list = new SortedDictionary<string, T>(); private static Regex split = new Regex(@"\s+"); public T[] CmdList { get { return cmd_list.Values.ToArray(); } } public CommandList() { Type type = typeof(T); List<Type> allcmd = ReflectionUtil.GetNoneVirtualSubTypes(type, type.Assembly); foreach (Type tcmd in allcmd) { T cmd = ReflectionUtil.CreateInstance(tcmd) as T; if (cmd != null) { cmd_list.Add(cmd.Key, cmd); } } } public bool DoCommand(string line, TextWriter output) { foreach (AbstractCommand cmd in cmd_list.Values) { if (line.ToLower().StartsWith(cmd.Key.ToLower())) { var arg = line.Substring(cmd.Key.Length); if (arg.Trim().Length > 0) { var mat = split.Match(arg); if (!mat.Success || mat.Index != 0) { continue; } } try { if (line.EndsWith("/?") || line.EndsWith("/help")) { output.WriteLine(cmd.Help); } else { cmd.DoCommand(arg.Trim(), output); } } catch (Exception err) { output.WriteLine(err.Message); } return true; } } return false; } public string ListCommand(string prefix) { List<AbstractCommand> cmdlist = new List<AbstractCommand>(); SortedDictionary<string, List<AbstractCommand>> catgory_map = new SortedDictionary<string, List<AbstractCommand>>(); foreach (AbstractCommand cmd in CmdList) { DescAttribute desc = PropertyUtil.GetAttribute<DescAttribute>(cmd.GetType()); if (desc == null || string.IsNullOrEmpty(desc.Category)) { cmdlist.Add(cmd); } else { List<AbstractCommand> catgory; if (!catgory_map.TryGetValue(desc.Category, out catgory)) { catgory = new List<AbstractCommand>(); catgory_map.Add(desc.Category, catgory); } catgory.Add(cmd); } } StringBuilder sb = new StringBuilder(); ListCommand_Internal(sb, prefix, cmdlist); foreach (KeyValuePair<string, List<AbstractCommand>> catgory in catgory_map) { sb.AppendLine("[" + catgory.Key + "]"); ListCommand_Internal(sb, prefix, catgory.Value); } return sb.ToString(); } private void ListCommand_Internal(StringBuilder sb, string prefix, List<AbstractCommand> cmdlist) { bool show_prefix = string.IsNullOrEmpty(prefix); foreach (AbstractCommand cmd in cmdlist) { if (show_prefix || cmd.Key.StartsWith(prefix)) { string line = cmd.Key; DescAttribute desc = PropertyUtil.GetAttribute<DescAttribute>(cmd.GetType()); if (desc != null) { line += "\t - " + desc.Desc; } sb.AppendLine(line); } } } } }