/// <summary> /// Traverses through each option within an option contract and performs specific operation. /// </summary> /// <param name="optionContract">The option contract to be traversed.</param> /// <param name="handler">The operation which should be taken on the option.</param> private void TraverseOptions(OptionContractBase optionContract, OptionTraversalEventHandler handler) { foreach (PropertyInfo property in optionContract.GetType().GetProperties()) { //foreach (object customAttribute in property.GetCustomAttributes(false)) //{ // if (customAttribute is OptionAttribute) // { // handler(optionContract, property, customAttribute as OptionAttribute); // break; // } //} object[] customAttributes = property.GetCustomAttributes(typeof(OptionAttribute), false); if (customAttributes.Length > 0) { OptionAttribute optionAttribute = customAttributes.First() as OptionAttribute; handler(optionContract, property, optionAttribute); } } }
/// <summary> /// Populates the property of a patternized contract with the values which come from the /// command line argument. /// </summary> /// <param name="target">The instance of an option contract to be populated.</param> /// <param name="property">The reflection information of the property to which the value should be populated.</param> /// <param name="attribute">The option attribute on the property.</param> /// <exception cref="AdaptiveConsole.ArgumentMissingException">Throws when an option is a required option but it is not specified in the command line arguments.</exception> /// <exception cref="AdaptiveConsole.InvalidOptionException">Throws when an invalid option type is provided.</exception> private void PopulateContractOption(OptionContractBase target, PropertyInfo property, OptionAttribute attribute) { bool containsOption = false; string optionName = string.Empty; switch (attribute.Type) { // If the option is a swith, and there is an occurrence in the command line argument, // that means the swith is turn on and we set the property to True. If there is no // occurrence of the option in the command line argument, it means that the switch // is turn off. case OptionType.Switch: foreach (ArgumentInfo arg in this.Arguments) { if (this.ContainsOption(attribute.Name, arg.Argument, attribute.CaseSensitive, OPTION_ATTRIBUTE_NAME_SEP)) { arg.Category = ArgumentCategory.Option; containsOption = true; break; } } if (containsOption) property.SetValue(target, true, null); else property.SetValue(target, false, null); break; // If the option is a single value option, for each command line argument, we firstly // try getting the option name and value from the argument. If failed in getting the name // and value, that means current argument is not a single value option, we iterates to // the next command line argument. If we successfully get the name and value from the // single value option, we then check if the option name contains the name of the argument. // If it does, that means this is the command line argument that we want and we should populate // the option value to the property of the option. case OptionType.SingleValue: optionName = string.Empty; string optionValue = string.Empty; foreach (ArgumentInfo arg in this.Arguments) { if (!this.GetSingleValue(arg.Argument, ref optionName, ref optionValue, OPTION_NAME_VALUE_SEP)) continue; if (this.ContainsOption(attribute.Name, optionName, attribute.CaseSensitive, OPTION_ATTRIBUTE_NAME_SEP)) { arg.Category = ArgumentCategory.Option; containsOption = true; break; } } if (containsOption) property.SetValue(target, optionValue, null); else { if (!attribute.Required) { // Sunny Chen Modified Begin - 9/20/2008 - Added for handling the Default field of the option. if (!attribute.Default.Equals(string.Empty)) property.SetValue(target, attribute.Default, null); else property.SetValue(target, string.Empty, null); // Sunny Chen Modified End } else throw new ArgumentMissingException("Argument {0} is required.", attribute.Name); } break; // If the option is a multiple value option, for each command line argument, we firstly // try getting the option name and values from the argument. If failed in getting the name // and values, that means current argument is not a multiple value option, we iterates to // the next command line argument. If we successfully get the name and values from the // multiple value option, we then check if the option name contains the name of the argument. // If it does, that means this is the command line argument that we want and we should populate // the option values to the property of the option. case OptionType.ValueList: optionName = string.Empty; string[] optionValues = null; foreach (ArgumentInfo arg in this.Arguments) { if (!this.GetMultipleValues(arg.Argument, ref optionName, ref optionValues, OPTION_NAME_VALUE_SEP, attribute.ValueSeparator)) continue; if (this.ContainsOption(attribute.Name, optionName, attribute.CaseSensitive, OPTION_ATTRIBUTE_NAME_SEP)) { arg.Category = ArgumentCategory.Option; containsOption = true; break; } } if (containsOption) property.SetValue(target, optionValues, null); else { if (!attribute.Required) property.SetValue(target, null, null); else throw new ArgumentMissingException("Argument {0} is required.", attribute.Name); } break; default: throw new InvalidOptionException("The option is of the invalid type."); } }