using System; using System.Diagnostics; public partial class Program { public static void Main(string[] args) { string errorMessage; CommandLineInfo commandLine = new CommandLineInfo(); if (!CommandLineHandler.TryParse( args, commandLine, out errorMessage)) { Console.WriteLine(errorMessage); DisplayHelp(); } if (commandLine.Help) { DisplayHelp(); } else { if (commandLine.Priority != ProcessPriorityClass.Normal) { // Change thread priority } } // ... } private static void DisplayHelp() { // Display the command-line help. Console.WriteLine( "Thankyou for contacting the help text"); } } ____________________________________________________________________________ ____________________________________________________________________________ using System; using System.Diagnostics; public partial class Program { private class CommandLineInfo { [CommandLineSwitchAlias("?")] public bool Help { get { return _Help; } set { _Help = value; } } private bool _Help; [CommandLineSwitchRequired] [CommandLineSwitchAlias("FileName")] public string Out { get { return _Out; } set { _Out = value; } } private string _Out; public ProcessPriorityClass Priority { get { return _Priority; } set { _Priority = value; } } private ProcessPriorityClass _Priority = ProcessPriorityClass.Normal; } } using System; using System.Diagnostics; using System.Reflection; public class CommandLineHandler { public static void Parse(string[] args, object commandLine) { string errorMessage; if (!TryParse(args, commandLine, out errorMessage)) { throw new ApplicationException(errorMessage); } } public static bool TryParse(string[] args, object commandLine, out string errorMessage) { bool success = false; errorMessage = null; foreach (string arg in args) { string option; if (arg[0] == '/' || arg[0] == '-') { string[] optionParts = arg.Split( new char[] { ':' }, 2); // Remove the slash|dash option = optionParts[0].Remove(0, 1); PropertyInfo property = commandLine.GetType().GetProperty(option, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public); if (property != null) { if (property.PropertyType == typeof(bool)) { // Last parameters for handling indexers property.SetValue( commandLine, true, null); success = true; } else if ( property.PropertyType == typeof(string)) { property.SetValue( commandLine, optionParts[1], null); success = true; } else if (property.PropertyType.IsEnum) { try { property.SetValue(commandLine, Enum.Parse( typeof(ProcessPriorityClass), optionParts[1], true), null); success = true; } catch (ArgumentException ) { success = false; errorMessage = string.Format( "The option '{0}' is " + "invalid for '{1}'", optionParts[1], option); } } else { success = false; errorMessage = string.Format( "Data type '{0}' on {1} is not" + " supported.", property.PropertyType.ToString(), commandLine.GetType().ToString()); } } else { success = false; errorMessage = string.Format( "Option '{0}' is not supported.", option); } } } return success; } } ______________________________________________________________________________ ______________________________________________________________________________ using System; using System.Collections.Specialized; using System.Reflection; [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class CommandLineSwitchRequiredAttribute : Attribute { public static string[] GetMissingRequiredOptions( object commandLine) { StringCollection missingOptions = new StringCollection(); PropertyInfo[] properties = commandLine.GetType().GetProperties(); foreach (PropertyInfo property in properties) { Attribute[] attributes = (Attribute[])property.GetCustomAttributes( typeof(CommandLineSwitchRequiredAttribute), false); if ((attributes.Length > 0) && (property.GetValue(commandLine, null) == null)) { if (property.GetValue(commandLine, null) == null) { missingOptions.Add(property.Name); } } } string[] results = new string[missingOptions.Count]; missingOptions.CopyTo(results, 0); return results; } } ______________________________________________________________________________ ______________________________________________________________________________ using System; using System.Reflection; using System.Collections.Generic; [AttributeUsage(AttributeTargets.Property)] public class CommandLineSwitchAliasAttribute : Attribute { public CommandLineSwitchAliasAttribute(string alias) { Alias = alias; } public string Alias { get { return _Alias; } set { _Alias = value; } } private string _Alias; public static Dictionary<string, PropertyInfo> GetSwitches( object commandLine) { PropertyInfo[] properties = null; Dictionary<string, PropertyInfo> options = new Dictionary<string, PropertyInfo>(); properties = commandLine.GetType().GetProperties( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (PropertyInfo property in properties) { options.Add(property.Name.ToLower(), property); foreach (CommandLineSwitchAliasAttribute attribute in property.GetCustomAttributes( typeof(CommandLineSwitchAliasAttribute), false)) { options.Add(attribute.Alias.ToLower(), property); } } return options; } } _____________________________________________________________________________ _____________________________________________________________________________ using System; using System.Reflection; using System.Collections.Generic; public class CommandLineHandler { // ... public static bool TryParse( string[] args, object commandLine, out string errorMessage) { bool success = false; errorMessage = null; Dictionary<string, PropertyInfo> options = CommandLineSwitchAliasAttribute.GetSwitches( commandLine); foreach (string arg in args) { PropertyInfo property; string option; if (arg[0] == '/' || arg[0] == '-') { string[] optionParts = arg.Split( new char[] { ':' }, 2); option = optionParts[0].Remove(0, 1).ToLower(); if (options.TryGetValue(option, out property)) { success = SetOption( commandLine, property, optionParts, ref errorMessage); } else { success = false; errorMessage = string.Format( "Option '{0}' is not supported.", option); } } } return success; } private static bool SetOption( object commandLine, PropertyInfo property, string[] optionParts, ref string errorMessage) { bool success; if (property.PropertyType == typeof(bool)) { // Last parameters for handling indexers property.SetValue( commandLine, true, null); success = true; } else { if ((optionParts.Length < 2) || optionParts[1] == "" || optionParts[1] == ":") { // No setting was provided for the switch. success = false; errorMessage = string.Format( "You must specify the value for the {0} option.", property.Name); } else if ( property.PropertyType == typeof(string)) { property.SetValue( commandLine, optionParts[1], null); success = true; } else if (property.PropertyType.IsEnum) { success = TryParseEnumSwitch( commandLine, optionParts, property, ref errorMessage); } else { success = false; errorMessage = string.Format( "Data type '{0}' on {1} is not supported.", property.PropertyType.ToString(), commandLine.GetType().ToString()); } } return success; } } |