/CommandLineParser/CommandLineParser/CommandLineParser.cs

# · C# · 734 lines · 502 code · 81 blank · 151 comment · 94 complexity · 6e3e45423890360367cade2462cb362d MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Reflection;
  5. using System.Text.RegularExpressions;
  6. using CommandLineParser.Arguments;
  7. using CommandLineParser.Exceptions;
  8. using CommandLineParser.Validation;
  9. namespace CommandLineParser
  10. {
  11. /// <summary>
  12. /// CommandLineParser allows user to define command line arguments and then parse
  13. /// the arguments from the command line.
  14. /// </summary>
  15. /// <include file='Doc/CommandLineParser.xml' path='CommandLineParser/Parser/*' />
  16. public class CommandLineParser
  17. {
  18. #region property backing fields
  19. private List<Argument> arguments = new List<Argument>();
  20. private List<ArgumentCertification> certifications = new List<ArgumentCertification>();
  21. private Dictionary<char, Argument> shortNameLookup;
  22. private Dictionary<string, Argument> longNameLookup;
  23. readonly Dictionary<string, Argument> ignoreCaseLookupDirectory = new Dictionary<string, Argument>();
  24. private string[] argsNotParsed;
  25. private bool showUsageOnEmptyCommandline = false;
  26. private bool checkMandatoryArguments = true;
  27. private bool checkArgumentCertifications = true;
  28. private bool allowShortSwitchGrouping = true;
  29. private readonly AdditionalArgumentsSettings additionalArgumentsSettings = new AdditionalArgumentsSettings();
  30. private readonly List<string> showUsageCommands = new List<string> { "--help", "/?", "/help" };
  31. private string showUsageHeader;
  32. private string showUsageFooter;
  33. private bool acceptSlash = true;
  34. private bool acceptHyphen = true;
  35. private bool ignoreCase;
  36. private bool acceptEqualSignSyntaxForValueArguments;
  37. private bool parsingSucceeded;
  38. #endregion
  39. /// <summary>
  40. /// Defined command line arguments
  41. /// </summary>
  42. public List<Argument> Arguments
  43. {
  44. get { return arguments; }
  45. set { arguments = value; }
  46. }
  47. /// <summary>
  48. /// Set of <see cref="ArgumentCertification">certifications</see> - certifications can be used to define
  49. /// which argument combinations are allowed and such type of validations.
  50. /// </summary>
  51. /// <seealso cref="CheckArgumentCertifications"/>
  52. /// <seealso cref="ArgumentCertification"/>
  53. /// <seealso cref="ArgumentGroupCertification"/>
  54. /// <seealso cref="DistinctGroupsCertification"/>
  55. public List<ArgumentCertification> Certifications
  56. {
  57. get { return certifications; }
  58. set { certifications = value; }
  59. }
  60. /// <summary>
  61. /// Allows more specific definition of additional arguments
  62. /// (arguments after those with - and -- prefix).
  63. /// </summary>
  64. public AdditionalArgumentsSettings AdditionalArgumentsSettings
  65. {
  66. get { return additionalArgumentsSettings; }
  67. }
  68. /// <summary>
  69. /// Text printed in the beginning of 'show usage'
  70. /// </summary>
  71. public string ShowUsageHeader
  72. {
  73. get { return showUsageHeader; }
  74. set { showUsageHeader = value; }
  75. }
  76. /// <summary>
  77. /// Text printed in the end of 'show usage'
  78. /// </summary>
  79. public string ShowUsageFooter
  80. {
  81. get { return showUsageFooter; }
  82. set { showUsageFooter = value; }
  83. }
  84. /// <summary>
  85. /// Arguments that directly invoke <see cref="ShowUsage()"/>. By default this is --help and /?.
  86. /// </summary>
  87. public IList <string> ShowUsageCommands
  88. {
  89. get
  90. {
  91. return showUsageCommands;
  92. }
  93. }
  94. /// <summary>
  95. /// When set to true, usage help is printed on the console when command line is without arguments.
  96. /// Default is false.
  97. /// </summary>
  98. public bool ShowUsageOnEmptyCommandline
  99. {
  100. get { return showUsageOnEmptyCommandline; }
  101. set { showUsageOnEmptyCommandline = value; }
  102. }
  103. /// <summary>
  104. /// When set to true, <see cref="MandatoryArgumentNotSetException"/> is thrown when some of the non-optional argument
  105. /// is not found on the command line. Default is true.
  106. /// See: <see cref="Argument.Optional"/>
  107. /// </summary>
  108. public bool CheckMandatoryArguments
  109. {
  110. get { return checkMandatoryArguments; }
  111. set { checkMandatoryArguments = value; }
  112. }
  113. /// <summary>
  114. /// When set to true, arguments are certified (using set of <see cref="Certifications"/>) after parsing.
  115. /// Default is true.
  116. /// </summary>
  117. public bool CheckArgumentCertifications
  118. {
  119. get { return checkArgumentCertifications; }
  120. set { checkArgumentCertifications = value; }
  121. }
  122. /// <summary>
  123. /// When set to true (default) <see cref="SwitchArgument">switch arguments</see> can be grouped on the command line.
  124. /// (e.g. -a -b -c can be written as -abc). When set to false and such a group is found, <see cref="CommandLineFormatException"/> is thrown.
  125. /// </summary>
  126. public bool AllowShortSwitchGrouping
  127. {
  128. get { return allowShortSwitchGrouping; }
  129. set { allowShortSwitchGrouping = value; }
  130. }
  131. /// <summary>
  132. /// Allows arguments in /a and /arg format
  133. /// </summary>
  134. public bool AcceptSlash
  135. {
  136. get { return acceptSlash; }
  137. set { acceptSlash = value; }
  138. }
  139. /// <summary>
  140. /// Allows arguments in -a and --arg format
  141. /// </summary>
  142. public bool AcceptHyphen
  143. {
  144. get { return acceptHyphen; }
  145. set { acceptHyphen = value; }
  146. }
  147. /// <summary>
  148. /// Argument names case insensitive (--OUTPUT or --output are treated equally)
  149. /// </summary>
  150. public bool IgnoreCase
  151. {
  152. get { return ignoreCase; }
  153. set { ignoreCase = value; }
  154. }
  155. /// <summary>
  156. /// When set to true, values of <see cref="ValueArgument{TValue}"/> are separeted by space,
  157. /// otherwise, they are separeted by equal sign and enclosed in quotation marks
  158. /// </summary>
  159. /// <example>
  160. /// --output="somefile.txt"
  161. /// </example>
  162. public bool AcceptEqualSignSyntaxForValueArguments
  163. {
  164. get { return acceptEqualSignSyntaxForValueArguments; }
  165. set { acceptEqualSignSyntaxForValueArguments = value; }
  166. }
  167. /// <summary>
  168. /// This property is set to true when <see cref="ParseCommandLine"/> finishes successfully.
  169. /// </summary>
  170. public bool ParsingSucceeded
  171. {
  172. get { return parsingSucceeded; }
  173. set { parsingSucceeded = value; }
  174. }
  175. /// <summary>
  176. /// Fills lookup dictionaries with arguments names and aliases
  177. /// </summary>
  178. private void InitializeArgumentLookupDictionaries()
  179. {
  180. shortNameLookup = new Dictionary<char, Argument>();
  181. longNameLookup = new Dictionary<string, Argument>();
  182. foreach (Argument argument in arguments)
  183. {
  184. if (argument.ShortName != ' ')
  185. {
  186. shortNameLookup.Add(argument.ShortName, argument);
  187. }
  188. foreach (char aliasChar in argument.ShortAliases)
  189. {
  190. shortNameLookup.Add(aliasChar, argument);
  191. }
  192. if (!String.IsNullOrEmpty(argument.LongName))
  193. {
  194. longNameLookup.Add(argument.LongName, argument);
  195. }
  196. foreach (string aliasString in argument.LongAliases)
  197. {
  198. longNameLookup.Add(aliasString, argument);
  199. }
  200. }
  201. ignoreCaseLookupDirectory.Clear();
  202. foreach (KeyValuePair<char, Argument> keyValuePair in shortNameLookup)
  203. {
  204. ignoreCaseLookupDirectory.Add(keyValuePair.Key.ToString().ToUpper(), keyValuePair.Value);
  205. }
  206. foreach (KeyValuePair<string, Argument> keyValuePair in longNameLookup)
  207. {
  208. ignoreCaseLookupDirectory.Add(keyValuePair.Key.ToUpper(), keyValuePair.Value);
  209. }
  210. }
  211. /// <summary>
  212. /// Resolves arguments from the command line and calls <see cref="Argument.Parse"/> on each argument.
  213. /// Additional arguments are stored in AdditionalArgumentsSettings.AdditionalArguments
  214. /// if AdditionalArgumentsSettings.AcceptAdditionalArguments is set to true.
  215. /// </summary>
  216. /// <exception cref="CommandLineFormatException">Command line arguments are not in correct format</exception>
  217. /// <param name="args">Command line arguments</param>
  218. public void ParseCommandLine(string[] args)
  219. {
  220. ParsingSucceeded = false;
  221. arguments.ForEach(delegate(Argument a) { a.Init(); });
  222. List<string> argsList = new List<string>(args);
  223. InitializeArgumentLookupDictionaries();
  224. ExpandValueArgumentsWithEqualSigns(argsList);
  225. ExpandShortSwitches(argsList);
  226. AdditionalArgumentsSettings.AdditionalArguments = new string[0];
  227. this.argsNotParsed = args;
  228. if ((args.Length == 0 && ShowUsageOnEmptyCommandline) ||
  229. (args.Length == 1 && showUsageCommands.Contains(args[0])))
  230. {
  231. ShowUsage();
  232. return;
  233. }
  234. if (args.Length > 0)
  235. {
  236. int argIndex;
  237. for (argIndex = 0; argIndex < argsList.Count;)
  238. {
  239. string curArg = argsList[argIndex];
  240. Argument argument = ParseArgument(curArg);
  241. if (argument == null)
  242. break;
  243. argument.Parse(argsList, ref argIndex);
  244. argument.UpdateBoundObject();
  245. }
  246. ParseAdditionalArguments(argsList, argIndex);
  247. }
  248. foreach (Argument argument in arguments)
  249. {
  250. if (argument is IArgumentWithDefaultValue && !argument.Parsed)
  251. {
  252. argument.UpdateBoundObject();
  253. }
  254. }
  255. PerformMandatoryArgumentsCheck();
  256. PerformCertificationCheck();
  257. ParsingSucceeded = true;
  258. }
  259. /// <summary>
  260. /// Searches <paramref name="parsingTarget"/> for fields with
  261. /// <see cref="ArgumentAttribute">ArgumentAttributes</see> or some of its descendats. Adds new argument
  262. /// for each such a field and defines binding of the argument to the field.
  263. /// Also adds <see cref="ArgumentCertification"/> object to <see cref="Certifications"/> collection
  264. /// for each <see cref="ArgumentCertificationAttribute"/> of <paramref name="parsingTarget"/>.
  265. /// </summary>
  266. /// <seealso cref="Argument.Bind"/>
  267. /// <param name="parsingTarget">object where you with some ArgumentAttributes</param>
  268. public void ExtractArgumentAttributes(object parsingTarget)
  269. {
  270. Type targetType = parsingTarget.GetType();
  271. MemberInfo[] fields = targetType.GetFields();
  272. MemberInfo[] properties = targetType.GetProperties();
  273. List<MemberInfo> fieldAndProps = new List<MemberInfo>(fields);
  274. fieldAndProps.AddRange(properties);
  275. foreach (MemberInfo info in fieldAndProps)
  276. {
  277. object[] attrs = info.GetCustomAttributes(typeof(ArgumentAttribute), true);
  278. if (attrs.Length == 1 && attrs[0] is ArgumentAttribute)
  279. {
  280. this.Arguments.Add(((ArgumentAttribute) attrs[0]).Argument);
  281. ((ArgumentAttribute) attrs[0]).Argument.Bind =
  282. new FieldArgumentBind(parsingTarget, info.Name);
  283. }
  284. }
  285. object[] typeAttrs = targetType.GetCustomAttributes(typeof(ArgumentCertificationAttribute), true);
  286. foreach (object certificationAttr in typeAttrs)
  287. {
  288. this.Certifications.Add(((ArgumentCertificationAttribute) certificationAttr).Certification);
  289. }
  290. }
  291. /// <summary>
  292. /// Parses one argument on the command line, lookups argument in <see cref="Arguments"/> using
  293. /// lookup dictionaries.
  294. /// </summary>
  295. /// <param name="curArg">argument string (including '-' or '--' prefixes)</param>
  296. /// <returns>Look-uped Argument class</returns>
  297. /// <exception cref="CommandLineFormatException">Command line is in the wrong format</exception>
  298. /// <exception cref="UnknownArgumentException">Unknown argument found.</exception>
  299. private Argument ParseArgument(string curArg)
  300. {
  301. if (curArg[0] == '-')
  302. {
  303. if (AcceptHyphen)
  304. {
  305. string argName;
  306. if (curArg.Length > 1)
  307. {
  308. if (curArg[1] == '-')
  309. {
  310. //long name
  311. argName = curArg.Substring(2);
  312. if (argName.Length == 1)
  313. {
  314. throw new CommandLineFormatException(String.Format(
  315. Messages.EXC_FORMAT_SHORTNAME_PREFIX, argName));
  316. }
  317. }
  318. else
  319. {
  320. //short name
  321. argName = curArg.Substring(1);
  322. if (argName.Length != 1)
  323. {
  324. throw new CommandLineFormatException(
  325. String.Format(Messages.EXC_FORMAT_LONGNAME_PREFIX, argName));
  326. }
  327. }
  328. Argument argument = LookupArgument(argName);
  329. if (argument != null) return argument;
  330. else
  331. throw new UnknownArgumentException(string.Format(Messages.EXC_ARG_UNKNOWN, argName), argName);
  332. }
  333. else
  334. {
  335. throw new CommandLineFormatException(Messages.EXC_FORMAT_SINGLEHYPHEN);
  336. }
  337. }
  338. else
  339. return null;
  340. }
  341. else if (curArg[0] == '/')
  342. {
  343. if (AcceptSlash)
  344. {
  345. if (curArg.Length > 1)
  346. {
  347. if (curArg[1] == '/')
  348. {
  349. throw new CommandLineFormatException(Messages.EXC_FORMAT_SINGLESLASH);
  350. }
  351. string argName = curArg.Substring(1);
  352. Argument argument = LookupArgument(argName);
  353. if (argument != null) return argument;
  354. else throw new UnknownArgumentException(string.Format(Messages.EXC_ARG_UNKNOWN, argName), argName);
  355. }
  356. else
  357. {
  358. throw new CommandLineFormatException(Messages.EXC_FORMAT_DOUBLESLASH);
  359. }
  360. }
  361. else
  362. return null;
  363. }
  364. else
  365. /*
  366. * curArg does not start with '-' character and therefore it is considered additional argument.
  367. * Argument parsing ends here.
  368. */
  369. return null;
  370. }
  371. /// <summary>
  372. /// Checks whether or non-optional arguments were defined on the command line.
  373. /// </summary>
  374. /// <exception cref="MandatoryArgumentNotSetException"><see cref="Argument.Optional">Non-optional</see> argument not defined.</exception>
  375. /// <seealso cref="CheckMandatoryArguments"/>, <seealso cref="Argument.Optional"/>
  376. private void PerformMandatoryArgumentsCheck()
  377. {
  378. arguments.ForEach(delegate (Argument arg)
  379. {
  380. if (!arg.Optional && !arg.Parsed)
  381. throw new MandatoryArgumentNotSetException(string.Format(Messages.EXC_MISSING_MANDATORY_ARGUMENT, arg.Name), arg.Name);
  382. });
  383. }
  384. /// <summary>
  385. /// Performs certifications
  386. /// </summary>
  387. private void PerformCertificationCheck()
  388. {
  389. certifications.ForEach(delegate (ArgumentCertification certification)
  390. {
  391. certification.Certify(this);
  392. });
  393. }
  394. /// <summary>
  395. /// Parses the rest of the command line for additional arguments
  396. /// </summary>
  397. /// <param name="argsList">list of thearguments</param>
  398. /// <param name="i">index of the first additional argument in <paramref name="argsList"/></param>
  399. /// <exception cref="CommandLineFormatException">Additional arguments found, but they are
  400. /// not accepted</exception>
  401. private void ParseAdditionalArguments(List<string> argsList, int i)
  402. {
  403. if (AdditionalArgumentsSettings.AcceptAdditionalArguments)
  404. {
  405. AdditionalArgumentsSettings.AdditionalArguments = new string[argsList.Count - i];
  406. if (i < argsList.Count)
  407. {
  408. Array.Copy(argsList.ToArray(), i, AdditionalArgumentsSettings.AdditionalArguments, 0, argsList.Count - i);
  409. }
  410. AdditionalArgumentsSettings.ProcessArguments();
  411. }
  412. else
  413. {
  414. throw new CommandLineFormatException(
  415. Messages.EXC_ADDITIONAL_ARGUMENTS_FOUND);
  416. }
  417. }
  418. /// <summary>
  419. /// If <see cref="AllowShortSwitchGrouping"/> is set to true, each group of switch arguments (e. g. -abcd)
  420. /// is expanded into full format (-a -b -c -d) in the list.
  421. /// </summary>
  422. /// <exception cref="CommandLineFormatException">Argument of type differnt from SwitchArgument found in one of the groups. </exception>
  423. /// <param name="argsList">List of arguments</param>
  424. /// <exception cref="CommandLineFormatException">Arguments that are not <see cref="SwitchArgument">switches</see> found
  425. /// in a group.</exception>
  426. /// <seealso cref="AllowShortSwitchGrouping"/>
  427. private void ExpandShortSwitches(IList<string> argsList)
  428. {
  429. if (AllowShortSwitchGrouping)
  430. {
  431. for (int i = 0; i < argsList.Count; i++)
  432. {
  433. string arg = argsList[i];
  434. if (arg.Length > 2)
  435. {
  436. if (arg[0] == '/' && arg[1] != '/' && AcceptSlash && longNameLookup.ContainsKey(arg.Substring(1)))
  437. continue;
  438. if (ShowUsageCommands.Contains(arg))
  439. continue;
  440. char sep = arg[0];
  441. if ((arg[0] == '-' && arg[1] != '-' && AcceptHyphen)
  442. || (arg[0] == '/' && arg[1] != '/' && AcceptSlash))
  443. {
  444. argsList.RemoveAt(i);
  445. //arg ~ -xyz
  446. foreach (char c in arg.Substring(1))
  447. {
  448. if (shortNameLookup.ContainsKey(c) && !(shortNameLookup[c] is SwitchArgument))
  449. {
  450. throw new CommandLineFormatException(
  451. string.Format(Messages.EXC_BAD_ARG_IN_GROUP, c));
  452. }
  453. argsList.Insert(i, sep.ToString() + c);
  454. i++;
  455. }
  456. }
  457. }
  458. }
  459. }
  460. }
  461. private void ExpandValueArgumentsWithEqualSigns(IList<string> argsList)
  462. {
  463. if (AcceptEqualSignSyntaxForValueArguments)
  464. {
  465. for (int i = 0; i < argsList.Count; i++)
  466. {
  467. string arg = argsList[i];
  468. Regex r = new Regex("(.*)=\"(.*)\"");
  469. if (AcceptEqualSignSyntaxForValueArguments && r.IsMatch(arg))
  470. {
  471. Match m = r.Match(arg);
  472. string argNameWithSep = m.Groups[1].Value;
  473. string argName = argNameWithSep;
  474. while (argName.StartsWith("-") && AcceptHyphen)
  475. argName = argName.Substring(1);
  476. while (argName.StartsWith("/") && AcceptSlash)
  477. argName = argName.Substring(1);
  478. string argValue = m.Groups[2].Value;
  479. Argument argument = LookupArgument(argName);
  480. if (argument is IValueArgument)
  481. {
  482. argsList.RemoveAt(i);
  483. argsList.Insert(i, argNameWithSep);
  484. i++;
  485. argsList.Insert(i, argValue);
  486. }
  487. }
  488. }
  489. }
  490. }
  491. /// <summary>
  492. /// Returns argument of given name
  493. /// </summary>
  494. /// <param name="argName">Name of the argument (<see cref="Argument.ShortName"/>, <see cref="Argument.LongName"/>, or alias)</param>
  495. /// <returns>Found argument or null when argument is not present</returns>
  496. public Argument LookupArgument(string argName)
  497. {
  498. if (argName.Length == 1)
  499. {
  500. if (shortNameLookup.ContainsKey(argName[0]))
  501. {
  502. return shortNameLookup[argName[0]];
  503. }
  504. }
  505. else
  506. {
  507. if (longNameLookup.ContainsKey(argName))
  508. {
  509. return longNameLookup[argName];
  510. }
  511. }
  512. if (IgnoreCase && ignoreCaseLookupDirectory.ContainsKey(argName.ToUpper()))
  513. {
  514. return ignoreCaseLookupDirectory[argName.ToUpper()];
  515. }
  516. // argument not found anywhere
  517. return null;
  518. }
  519. /// <summary>
  520. /// Prints arguments information and usage information to
  521. /// the <paramref name="outputStream"/>.
  522. /// </summary>
  523. public void PrintUsage(TextWriter outputStream)
  524. {
  525. outputStream.WriteLine(ShowUsageHeader);
  526. outputStream.WriteLine(Messages.MSG_USAGE);
  527. foreach (Argument argument in arguments)
  528. {
  529. outputStream.Write("\t");
  530. bool comma = false;
  531. if (argument.ShortName != ' ')
  532. {
  533. outputStream.Write("-" + argument.ShortName);
  534. comma = true;
  535. }
  536. foreach (char c in argument.ShortAliases)
  537. {
  538. if (comma)
  539. outputStream.WriteLine(", ");
  540. outputStream.Write("-" + c);
  541. comma = true;
  542. }
  543. if (!String.IsNullOrEmpty(argument.LongName))
  544. {
  545. if (comma)
  546. outputStream.Write(", ");
  547. outputStream.Write("--" + argument.LongName);
  548. comma = true;
  549. }
  550. foreach (string str in argument.LongAliases)
  551. {
  552. if (comma)
  553. outputStream.Write(", ");
  554. outputStream.Write("--" + str);
  555. comma = true;
  556. }
  557. if (argument.Optional)
  558. outputStream.Write(Messages.MSG_OPTIONAL);
  559. outputStream.WriteLine("... {0} ", argument.Description);
  560. if (!String.IsNullOrEmpty(argument.Example))
  561. {
  562. outputStream.WriteLine(Messages.MSG_EXAMPLE_FORMAT, argument.Example);
  563. }
  564. if (!String.IsNullOrEmpty(argument.FullDescription))
  565. {
  566. outputStream.WriteLine();
  567. outputStream.WriteLine(argument.FullDescription);
  568. }
  569. outputStream.WriteLine();
  570. }
  571. if (Certifications.Count > 0)
  572. {
  573. outputStream.WriteLine(Messages.CERT_REMARKS);
  574. foreach (ArgumentCertification certification in Certifications)
  575. {
  576. outputStream.WriteLine("\t" + certification.GetDescription);
  577. }
  578. outputStream.WriteLine();
  579. }
  580. outputStream.WriteLine(ShowUsageFooter);
  581. }
  582. /// <summary>
  583. /// Prints arguments information and usage information to the console.
  584. /// </summary>
  585. public void ShowUsage()
  586. {
  587. PrintUsage(Console.Out);
  588. }
  589. /// <summary>
  590. /// Prints values of parsed arguments. Can be used for debugging.
  591. /// </summary>
  592. public void ShowParsedArguments()
  593. {
  594. Console.WriteLine(Messages.MSG_PARSING_RESULTS);
  595. Console.WriteLine("\t" + Messages.MSG_COMMAND_LINE);
  596. foreach (string arg in argsNotParsed)
  597. {
  598. Console.Write(arg);
  599. Console.Write(" ");
  600. }
  601. Console.WriteLine();
  602. Console.WriteLine();
  603. Console.WriteLine("\t" + Messages.MSG_PARSED_ARGUMENTS);
  604. foreach (Argument argument in arguments)
  605. {
  606. if (argument.Parsed)
  607. argument.PrintValueInfo();
  608. }
  609. Console.WriteLine();
  610. if (AdditionalArgumentsSettings.AcceptAdditionalArguments)
  611. {
  612. Console.WriteLine("\t" + Messages.MSG_ADDITIONAL_ARGUMENTS);
  613. foreach (string simpleArgument in AdditionalArgumentsSettings.AdditionalArguments)
  614. {
  615. Console.Write(simpleArgument + " ");
  616. }
  617. Console.WriteLine();
  618. Console.WriteLine();
  619. }
  620. }
  621. /// <summary>
  622. /// <para>
  623. /// Fills FullDescription of all the difined arguments from a resource file.
  624. /// For each argument selects a string from a resource that has the same resource key
  625. /// as is the currrent value of the argument's FullDescription.
  626. /// </para>
  627. /// <para>
  628. /// This way the value of FullDescription's can be set to keys and these keys are replaced by
  629. /// the resource values when the method is called.
  630. /// </para>
  631. /// </summary>
  632. /// <param name="resource">The resource.</param>
  633. public void FillDescFromResource(IResource resource)
  634. {
  635. foreach (Argument argument in Arguments)
  636. {
  637. if (!String.IsNullOrEmpty(argument.FullDescription))
  638. {
  639. string ld = resource.ResourceManager.GetString(argument.FullDescription);
  640. argument.FullDescription = ld;
  641. }
  642. }
  643. foreach (Argument argument in AdditionalArgumentsSettings.TypedAdditionalArguments)
  644. {
  645. if (!String.IsNullOrEmpty(argument.FullDescription))
  646. {
  647. string ld = resource.ResourceManager.GetString(argument.FullDescription);
  648. argument.FullDescription = ld;
  649. }
  650. }
  651. }
  652. }
  653. }