private static void SetFieldOrPropertyValue(MemberInfo mi, ICmdArgs cmdArgObj, Object value) { if (mi.MemberType == MemberTypes.Field) { ((FieldInfo)mi).SetValue(cmdArgObj, value); return; } if (mi.MemberType == MemberTypes.Property) { ((PropertyInfo)mi).SetValue(cmdArgObj, value, null); return; } throw new Exception <CmdArgumentTypeExceptionArgs>( String.Format(CultureInfo.CurrentCulture, "Member {0} must be a field or property.", mi.Name)); }
private static void SetFieldOrPropertyValue(MemberInfo mi, ICmdArgs cmdArgObj, Object value) { if (mi.MemberType == MemberTypes.Field) { ((FieldInfo) mi).SetValue(cmdArgObj, value); return; } if (mi.MemberType == MemberTypes.Property) { ((PropertyInfo) mi).SetValue(cmdArgObj, value, null); return; } throw new Exception<CmdArgumentTypeExceptionArgs>( String.Format(CultureInfo.CurrentCulture, "Member {0} must be a field or property.", mi.Name)); }
/// <summary> /// Parses a set of command-line arguments populating the fields/properties of an ICmdArgs class object. /// </summary> /// <param name="cmdArgObj">Identifies the object whose fields/properties /// should be set based on the command-line arguments.</param> /// <param name="args">Identifies the command-line arguments.</param> public static void Parse(ICmdArgs cmdArgObj, String[] args) { Contract.Requires((cmdArgObj != null) && (args != null)); IList<String> requiredSwitchNames = ValidateMembers(cmdArgObj.GetType()); for (Int32 arg = 0; arg < args.Length; arg++) { if ((args[arg][0] == '-') || (args[arg][0] == '/')) { // This argument is a switch, process it String switchName = null; String switchValue = String.Empty; // Default to what an optional value should be Boolean SwitchIncludesAValue = (args[arg].IndexOf(':') != -1); if (SwitchIncludesAValue) { // This switch includes a colon followed by a value // Separate the switch name from its value switchName = args[arg].Substring(1, args[arg].IndexOf(':') - 1); switchValue = args[arg].Substring(args[arg].IndexOf(':') + 1); } else { // This switch doesn't include a colon followed by a value switchName = args[arg].Substring(1); } // Lookup the switch member CmdArgAttribute caa; // Initialized by LookupMember MemberInfo mi = LookupMember(cmdArgObj.GetType(), switchName, SwitchIncludesAValue, out caa); if (caa.RequiredValue == CmdArgRequiredValue.No) { // This switch must NOT have a value, the switch's type must be Boolean if (GetFieldOrPropertyMemberType(mi) != typeof(Boolean)) { throw new Exception<CmdArgumentTypeExceptionArgs>( String.Format(CultureInfo.CurrentCulture, "The {0} switch must be of Boolean type.", mi.Name)); } // Since the switch is specified, turn this Boolean to true SetFieldOrPropertyValue(mi, cmdArgObj, true); } else { // This switch MAY have a value, the switch's type doesn't have to be Boolean Type switchType = GetFieldOrPropertyMemberType(mi); if (typeof(Enum).IsAssignableFrom(switchType)) { try { SetFieldOrPropertyValue(mi, cmdArgObj, Enum.Parse(switchType, switchValue, true)); } catch (ArgumentException) { if (!Attribute.IsDefined(switchType, typeof(FlagsAttribute), false)) { throw new Exception<InvalidCmdArgumentExceptionArgs>( new InvalidCmdArgumentExceptionArgs(switchName), String.Format(CultureInfo.CurrentCulture, "The {0} switch requires one of the following values: {1}.", switchName, String.Join(", ", Enum.GetNames(switchType)))); } else { throw new Exception<InvalidCmdArgumentExceptionArgs>( new InvalidCmdArgumentExceptionArgs(switchName), String.Format(CultureInfo.CurrentCulture, "The {0} switch requires a combination of the following values (comma separated): {1}.", switchName, String.Join(", ", Enum.GetNames(switchType)))); } } } else { SetFieldOrPropertyValue(mi, cmdArgObj, Convert.ChangeType(switchValue, switchType, CultureInfo.InvariantCulture)); } if (caa.RequiredArg) { // If we found a required switch, remove it from the list of required // switches. This list should be empty when done parsing or some // required switches weren't specified by the user. requiredSwitchNames.Remove(switchName); } } } else { // This is a free-form command-line argument, append it to a list cmdArgObj.ProcessStandAloneArgument(args[arg]); } } // We're done parsing command-line arguments, were any required switch unspecified? if (requiredSwitchNames.Count > 0) { String[] names = new String[requiredSwitchNames.Count]; requiredSwitchNames.CopyTo(names, 0); throw new Exception<InvalidCmdArgumentExceptionArgs>( new InvalidCmdArgumentExceptionArgs(String.Join(", ", names)), String.Format(CultureInfo.CurrentCulture, "The following required switch(es) must be specified: {0}.", String.Join(", ", names))); } // Let the user's type perform any desired validation cmdArgObj.Validate(); }
/// <summary> /// Parses a set of command-line arguments populating the fields/properties of an ICmdArgs class object. /// </summary> /// <param name="cmdArgObj">Identifies the object whose fields/properties /// should be set based on the command-line arguments.</param> /// <param name="args">Identifies the command-line arguments.</param> public static void Parse(ICmdArgs cmdArgObj, String[] args) { Contract.Requires((cmdArgObj != null) && (args != null)); IList <String> requiredSwitchNames = ValidateMembers(cmdArgObj.GetType()); for (Int32 arg = 0; arg < args.Length; arg++) { if ((args[arg][0] == '-') || (args[arg][0] == '/')) { // This argument is a switch, process it String switchName = null; String switchValue = String.Empty; // Default to what an optional value should be Boolean SwitchIncludesAValue = (args[arg].IndexOf(':') != -1); if (SwitchIncludesAValue) { // This switch includes a colon followed by a value // Separate the switch name from its value switchName = args[arg].Substring(1, args[arg].IndexOf(':') - 1); switchValue = args[arg].Substring(args[arg].IndexOf(':') + 1); } else { // This switch doesn't include a colon followed by a value switchName = args[arg].Substring(1); } // Lookup the switch member CmdArgAttribute caa; // Initialized by LookupMember MemberInfo mi = LookupMember(cmdArgObj.GetType(), switchName, SwitchIncludesAValue, out caa); if (caa.RequiredValue == CmdArgRequiredValue.No) { // This switch must NOT have a value, the switch's type must be Boolean if (GetFieldOrPropertyMemberType(mi) != typeof(Boolean)) { throw new Exception <CmdArgumentTypeExceptionArgs>( String.Format(CultureInfo.CurrentCulture, "The {0} switch must be of Boolean type.", mi.Name)); } // Since the switch is specified, turn this Boolean to true SetFieldOrPropertyValue(mi, cmdArgObj, true); } else { // This switch MAY have a value, the switch's type doesn't have to be Boolean Type switchType = GetFieldOrPropertyMemberType(mi); if (typeof(Enum).IsAssignableFrom(switchType)) { try { SetFieldOrPropertyValue(mi, cmdArgObj, Enum.Parse(switchType, switchValue, true)); } catch (ArgumentException) { if (!Attribute.IsDefined(switchType, typeof(FlagsAttribute), false)) { throw new Exception <InvalidCmdArgumentExceptionArgs>( new InvalidCmdArgumentExceptionArgs(switchName), String.Format(CultureInfo.CurrentCulture, "The {0} switch requires one of the following values: {1}.", switchName, String.Join(", ", Enum.GetNames(switchType)))); } else { throw new Exception <InvalidCmdArgumentExceptionArgs>( new InvalidCmdArgumentExceptionArgs(switchName), String.Format(CultureInfo.CurrentCulture, "The {0} switch requires a combination of the following values (comma separated): {1}.", switchName, String.Join(", ", Enum.GetNames(switchType)))); } } } else { SetFieldOrPropertyValue(mi, cmdArgObj, Convert.ChangeType(switchValue, switchType, CultureInfo.InvariantCulture)); } if (caa.RequiredArg) { // If we found a required switch, remove it from the list of required // switches. This list should be empty when done parsing or some // required switches weren't specified by the user. requiredSwitchNames.Remove(switchName); } } } else { // This is a free-form command-line argument, append it to a list cmdArgObj.ProcessStandAloneArgument(args[arg]); } } // We're done parsing command-line arguments, were any required switch unspecified? if (requiredSwitchNames.Count > 0) { String[] names = new String[requiredSwitchNames.Count]; requiredSwitchNames.CopyTo(names, 0); throw new Exception <InvalidCmdArgumentExceptionArgs>( new InvalidCmdArgumentExceptionArgs(String.Join(", ", names)), String.Format(CultureInfo.CurrentCulture, "The following required switch(es) must be specified: {0}.", String.Join(", ", names))); } // Let the user's type perform any desired validation cmdArgObj.Validate(); }