/// <summary> /// ## GetStrategyAliasMap /// /// Returns a mapping of all alias => class names for classes that implement the strategy. /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public static Dictionary <string, string> GetStrategyAliasMap <T>() { Dictionary <string, string> map = new Dictionary <string, string>(); // iterate over all strategy implementations // and pull alias from class attribute List <TypeInfo> types = GetStrategyImplementations <T>(); foreach (TypeInfo ti in types) { // then pull in from the attribute CommandAlias alias = ti.GetCustomAttribute <CommandAlias>(); if (alias != null) { foreach (string s in alias.Aliases) { if (map.ContainsKey(s)) { throw new Exception($"Duplicate alias defined for the type {ti.Name}: {s}"); } map[s] = ti.Name; } } else { // add the class name as the default "alias" map[ti.Name] = ti.Name; } } return(map); }
/// <summary> /// ## AddOption /// /// Adds a new option to the option set. /// </summary> /// <param name="options">OptionSet to add to.</param> /// <param name="strategies">List of strategy types to use for this option.</param> /// <param name="option">The option name.</param> /// <param name="action">The delegate to call for the option.</param> private void AddOption(OptionSet options, List <TypeInfo> strategies, string option, OptionAction <string, string> action) { /* * The terminology here is a bit confusing, so here is quick explanation: * - Option is the overall argument provided and the bit of text right after the hypen(s): --foo or -f * - Command is the part after the colon following the option: --foo:bar * This ties back directly to a strategy. * * So for the CLI argument `--select:regex=^foo\.txt$`, we get: * - option: select * - command: regex (refers to the RegexSelectionStrategy) * - command parameters: ^foo\.txt$ * * We are also using the first character of the command as a short alias, * so we can use `-s` instead of `--select` for example. */ // Let's use class attributes for each stategy to set the option command name // and build the option command description text. StringBuilder buffer = new StringBuilder($"The {option} strategy to use and any parameters to provide."); foreach (TypeInfo ti in strategies) { // default command alias for strategy is the class name string alias = ti.Name; string description = "(no description)"; CommandAlias commandAlias = ti.GetCustomAttribute <CommandAlias>(); if (commandAlias != null && commandAlias.Aliases.Count > 0) { alias = String.Join(", ", commandAlias.Aliases); } DescriptionAttribute descriptionAttr = ti.GetCustomAttribute <DescriptionAttribute>(); if (descriptionAttr != null) { description = descriptionAttr.Description; } // final constuct should look like: - foo, bar: My foobar description. buffer.Append($"\n - {alias}: {description}"); } // add the option: // f|foo: // The foo strategy to use... // delegate to call options.Add($"{option[0]}|{option}:", buffer.ToString(), action); }