// internals //internal CmdletInfo CreateGetCommandCopy(CmdletInfo cmdletInfo, object[] arguments); //internal object[] Arguments { set; get; } //internal string FullName { get; } //internal bool IsGetCommandCopy { set; get; } private CommandParameterInfo AddParameterToParameterSet(Dictionary <string, Collection <CommandParameterInfo> > paramSets, MemberInfo memberInfo, Type type, ParameterAttribute paramAttr) { CommandParameterInfo pi = new CommandParameterInfo(memberInfo, type, paramAttr); var paramSetName = paramAttr.ParameterSetName; // Determine if this parameter is uniquely defined for one set and rember it if (!String.IsNullOrEmpty(paramSetName) && !paramSetName.Equals(ParameterAttribute.AllParameterSets)) { var parameterName = pi.Name; // check if we already defined that parameter for another set if (UniqueSetParameters.ContainsKey(parameterName)) { UniqueSetParameters[parameterName] = null; } else { // not yet in any set, it's a candidate for a unique parameter UniqueSetParameters[parameterName] = paramSetName; } } paramSetName = paramSetName ?? ParameterAttribute.AllParameterSets; if (!paramSets.ContainsKey(paramSetName)) { paramSets.Add(paramSetName, new Collection <CommandParameterInfo>()); } Collection <CommandParameterInfo> paramSet = paramSets[paramSetName]; paramSet.Add(pi); return(pi); }
private static void AppendFormatCommandParameterInfo(CommandParameterInfo parameter, Text.StringBuilder result) { if (result.Length > 0) { // Add a space between parameters result.Append(" "); } if (parameter.ParameterType == typeof(SwitchParameter)) { result.AppendFormat(CultureInfo.InvariantCulture, parameter.IsMandatory ? "-{0}" : "[-{0}]", parameter.Name); } else { string parameterTypeString = GetParameterTypeString(parameter.ParameterType, parameter.Attributes); if (parameter.IsMandatory) { result.AppendFormat(CultureInfo.InvariantCulture, parameter.Position != int.MinValue ? "[-{0}] <{1}>" : "-{0} <{1}>", parameter.Name, parameterTypeString); } else { result.AppendFormat(CultureInfo.InvariantCulture, parameter.Position != int.MinValue ? "[[-{0}] <{1}>]" : "[-{0} <{1}>]", parameter.Name, parameterTypeString); } } }
private void BindParameter(CommandParameterInfo info, object value, bool doConvert) { var memberInfo = info.MemberInfo; if (_boundParameters.Contains(memberInfo)) { var msg = String.Format("Parameter '{0}' has already been bound!", info.Name); throw new ParameterBindingException(msg); } foreach (var attr in info.TransformationAttributes) { value = attr.Transform(_engineIntrinsics, value); } // ConvertTo throws an exception if conversion isn't possible. That's just fine. if (doConvert) { value = LanguagePrimitives.ConvertTo(value, info.ParameterType); } // TODO: validate value with Attributes (ValidateNotNullOrEmpty, etc) SetCommandValue(memberInfo, value); // make sure to update the candidate set to only consider parameter sets with the newly bound parameter RestrictCandidatesByBoundParameter(info); _boundParameters.Add(memberInfo); }
private bool TryBindParameter(CommandParameterInfo info, object value, bool doConvert) { try { BindParameter(info, value, doConvert); return(true); } catch (Exception) { return(false); } }
/// <summary> /// /// </summary> /// <param name="obj"></param> /// <remarks> /// All abount Cmdlet parameters: http://msdn2.microsoft.com/en-us/library/ms714433(VS.85).aspx /// </remarks> internal override void BindArguments(PSObject obj) { if ((obj == null) && (Parameters.Count == 0)) { return; } // TODO: bind the arguments to the parameters CommandParameterSetInfo paramSetInfo = _cmdletInfo.GetDefaultParameterSet(); // TODO: refer to the Command._ParameterSetName for a param set name if (obj != null) { foreach (CommandParameterInfo paramInfo in paramSetInfo.Parameters) { if (paramInfo.ValueFromPipeline) { BindArgument(paramInfo.Name, obj, paramInfo.ParameterType); } } } if (Parameters.Count > 0) { // bind by position location for (int i = 0; i < Parameters.Count; i++) { CommandParameterInfo paramInfo = null; CommandParameter parameter = Parameters[i]; if (string.IsNullOrEmpty(parameter.Name)) { paramInfo = paramSetInfo.GetParameterByPosition(i); if (paramInfo != null) { BindArgument(paramInfo.Name, parameter.Value, paramInfo.ParameterType); } } else { paramInfo = paramSetInfo.GetParameterByName(parameter.Name); if (paramInfo != null) { BindArgument(paramInfo.Name, parameter.Value, paramInfo.ParameterType); } } } } }
// restricts the candidate parameter sets by the newly bound parameters private void RestrictCandidatesByBoundParameter(CommandParameterInfo info) { var setsContaining = from paramSet in _cmdletInfo.ParameterSets where paramSet.Contains(info) select paramSet; _candidateParameterSets = _candidateParameterSets.Intersect(setsContaining).ToList(); if (_candidateParameterSets.Count == 0) { ThrowAmbiguousParameterSetException(); } else if (_candidateParameterSets.Count == 1) { _activeSet = _candidateParameterSets[0]; } }
private void AddParameterToParameterSet(Dictionary <string, Collection <CommandParameterInfo> > paramSets, CommandParameterInfo paramInfo) { var paramSetName = paramInfo.ParameterSetName; // create the parameter set if it doesn't exist, yet if (!paramSets.ContainsKey(paramSetName)) { paramSets.Add(paramSetName, new Collection <CommandParameterInfo>()); } Collection <CommandParameterInfo> paramSet = paramSets[paramSetName]; // actually add parameter to the set paramSet.Add(paramInfo); }
private void BindParameter(CommandParameterInfo info, object value, bool doConvert) { var memberInfo = info.MemberInfo; if (_boundParameters.Contains(memberInfo)) { var msg = String.Format("Parameter '{0}' has already been bound!", info.Name); throw new ParameterBindingException(msg); } // ConvertTo throws an exception if conversion isn't possible. That's just fine. if (doConvert) { value = LanguagePrimitives.ConvertTo(value, info.ParameterType); } SetCommandValue(memberInfo, value); _boundParameters.Add(memberInfo); }
private void RegisterParameter(CommandParameterInfo parameterInfo) { // also add it to lookuptable and check for unuque names/aliases var allNames = parameterInfo.Aliases.ToList(); allNames.Add(parameterInfo.Name); foreach (var curName in allNames) { if (ParameterInfoLookupTable.ContainsKey(curName)) { // save exception to be thrown when this object is validated, not now var msg = String.Format("The name or alias '{0}' is used multiple times.", curName); _validationException = new MetadataException(msg); continue; } ParameterInfoLookupTable[curName] = parameterInfo; } }
/// <summary> /// Creates an instance of the ShowCommandParameterInfo class based on a CommandParameterInfo object /// </summary> /// /// <param name="other"> /// The object to wrap. /// </param> public ShowCommandParameterInfo(CommandParameterInfo other) { if (null == other) { throw new ArgumentNullException("other"); } this.Name = other.Name; this.IsMandatory = other.IsMandatory; this.ValueFromPipeline = other.ValueFromPipeline; this.ParameterType = new ShowCommandParameterType(other.ParameterType); this.Position = other.Position; var validateSetAttribute = other.Attributes.Where(x => typeof(ValidateSetAttribute).IsAssignableFrom(x.GetType())).Cast<ValidateSetAttribute>().LastOrDefault(); if (validateSetAttribute != null) { this.HasParameterSet = true; this.ValidParamSetValues = validateSetAttribute.ValidValues; } }
// internals //internal CmdletInfo CreateGetCommandCopy(CmdletInfo cmdletInfo, object[] arguments); //internal object[] Arguments { set; get; } //internal string FullName { get; } //internal bool IsGetCommandCopy { set; get; } private CommandParameterInfo AddParameterToParameterSet(Dictionary <string, Collection <CommandParameterInfo> > paramSets, MemberInfo memberInfo, Type type, ParameterAttribute paramAttr) { CommandParameterInfo pi = new CommandParameterInfo(memberInfo, type, paramAttr); var paramSetName = paramAttr.ParameterSetName; // Determine if this parameter is uniquely defined for one set and rember it paramSetName = paramSetName ?? ParameterAttribute.AllParameterSets; if (!paramSets.ContainsKey(paramSetName)) { paramSets.Add(paramSetName, new Collection <CommandParameterInfo>()); } Collection <CommandParameterInfo> paramSet = paramSets[paramSetName]; paramSet.Add(pi); return(pi); }
internal CommandParameterInfo LookupParameter(string name) { CommandParameterInfo found = null; foreach (CommandParameterInfo parameter in Parameters) { if (parameter.Name.StartsWith(name, StringComparison.CurrentCultureIgnoreCase) || (parameter.Aliases != null && parameter.Aliases.Where(a => a.StartsWith(name, StringComparison.CurrentCultureIgnoreCase)).Count() > 0)) { // If match already found, name is ambiguous if (found != null) { //TODO: Throw ParameterBindingException when implemented throw new ArgumentException("Supplied parmameter '" + name + "' is ambiguous, possibilities include '" + found.Name + "' and '" + parameter.Name + "'"); } found = parameter; } } return(found); }
private static void AppendFormatCommandParameterInfo( CommandParameterInfo parameter, ref StringBuilder result) { if (result.Length > 0) { result.Append(" "); } if (parameter.ParameterType == typeof(bool) || parameter.ParameterType == typeof(SwitchParameter)) { if (parameter.IsMandatory) { result.AppendFormat("-{0}", (object)parameter.Name); } else { result.AppendFormat("[-{0}]", (object)parameter.Name); } } else if (parameter.IsMandatory) { if (parameter.Position != int.MinValue) { result.AppendFormat("[-{0}] <{1}>", (object)parameter.Name, (object)parameter.ParameterType.Name.ToString()); } else { result.AppendFormat("-{0} <{1}>", (object)parameter.Name, (object)parameter.ParameterType.Name.ToString()); } } else if (parameter.Position != int.MinValue) { result.AppendFormat("[[-{0}] <{1}>]", (object)parameter.Name, (object)parameter.ParameterType.Name.ToString()); } else { result.AppendFormat("[-{0} <{1}>]", (object)parameter.Name, (object)parameter.ParameterType.Name.ToString()); } }
private static void AppendFormatCommandParameterInfo(CommandParameterInfo parameter, ref StringBuilder result) { if (result.Length > 0) { result.Append(" "); } if (parameter.ParameterType == typeof(SwitchParameter)) { result.AppendFormat(parameter.IsMandatory ? "-{0}" : "[-{0}]", parameter.Name); } else { string parameterTypeString = GetParameterTypeString(parameter.ParameterType, parameter.Attributes); if (parameter.IsMandatory) { result.AppendFormat((parameter.Position != -2147483648) ? "[-{0}] <{1}>" : "-{0} <{1}>", parameter.Name, parameterTypeString); } else { result.AppendFormat((parameter.Position != -2147483648) ? "[[-{0}] <{1}>]" : "[-{0} <{1}>]", parameter.Name, parameterTypeString); } } }
private static void AppendFormatCommandParameterInfo(CommandParameterInfo parameter, ref StringBuilder result) { if (result.Length > 0) { result.Append(" "); } if (parameter.ParameterType == typeof(SwitchParameter)) { result.AppendFormat(parameter.IsMandatory ? "-{0}" : "[-{0}]", parameter.Name); } else { string parameterTypeString = GetParameterTypeString(parameter.ParameterType, parameter.Attributes); if (parameter.IsMandatory) { result.AppendFormat((parameter.Position != -2147483648) ? "[-{0}] <{1}>" : "-{0} <{1}>", parameter.Name, parameterTypeString); } else { result.AppendFormat((parameter.Position != -2147483648) ? "[[-{0}] <{1}>]" : "[-{0} <{1}>]", parameter.Name, parameterTypeString); } } }
/// <remarks> /// From MSDN article: http://msdn2.microsoft.com/en-us/library/ms714348(VS.85).aspx /// /// * A cmdlet can have any number of parameters. However, for a better user experience the number /// of parameters should be limited when possible. /// * Parameters must be declared on public non-static fields or properties. It is preferred for /// parameters to be declared on properties. The property must have a public setter, and if ValueFromPipeline /// or ValueFromPipelineByPropertyName is specified the property must have a public getter. /// * When specifying positional parameters, note the following. /// * Limit the number of positional parameters in a parameter set to less than five if possible. /// * Positional parameters do not have to be sequential; positions 5, 100, 250 works the same as positions 0, 1, 2. /// * When the Position keyword is not specified, the cmdlet parameter must be referenced by its name. /// * When using parameter sets, no parameter set should contain more than one positional parameter with the same position. /// * In addition, only one parameter in a set should declare ValueFromPipeline = true. Multiple parameters may define ValueFromPipelineByPropertyName = true. /// /// </remarks> private void GetParameterSetInfo(Type cmdletType) { Dictionary <string, Collection <CommandParameterInfo> > paramSets = new Dictionary <string, Collection <CommandParameterInfo> >(StringComparer.CurrentCultureIgnoreCase); // TODO: When using parameter sets, no parameter set should contain more than one positional parameter with the same position. // TODO: If not parameters have a position declared then positions for all the parameters should be automatically declaredin the order they are specified // TODO: Only one parameter in a set should declare ValueFromRemainingArguments = true // TODO: Only one parameter in a set should declare ValueFromPipeline = true. Multiple parameters may define ValueFromPipelineByPropertyName = true. // TODO: Currently due to the way parameters are loaded into sets from all set at the end the parameter end up in incorrect order. // get the name of the default parameter set string strDefaultParameterSetName = null; object[] cmdLetAttrs = cmdletType.GetCustomAttributes(typeof(CmdletAttribute), false); if (cmdLetAttrs.Length > 0) { strDefaultParameterSetName = ((CmdletAttribute)cmdLetAttrs[0]).DefaultParameterSetName; // If a default set is specified, it has to exist, even if it's empty. // See NonExisitingDefaultParameterSetIsEmptyPatameterSet reference test if (!String.IsNullOrEmpty(strDefaultParameterSetName)) { paramSets.Add(strDefaultParameterSetName, new Collection <CommandParameterInfo>()); } } // always have a parameter set for all parameters. even if we don't have any parameters or no parameters // that are in all sets. This will nevertheless save various checks if (!paramSets.ContainsKey(ParameterAttribute.AllParameterSets)) { paramSets.Add(ParameterAttribute.AllParameterSets, new Collection <CommandParameterInfo>()); } // Add fields with ParameterAttribute foreach (FieldInfo fieldInfo in cmdletType.GetFields(BindingFlags.Public | BindingFlags.Instance)) { System.Diagnostics.Debug.WriteLine(fieldInfo.ToString()); object[] attributes = fieldInfo.GetCustomAttributes(false); CommandParameterInfo last = null; // Find all [Parameter] attributes on the property foreach (object attr in attributes) { if (attr is ParameterAttribute) { last = AddParameterToParameterSet(paramSets, fieldInfo, fieldInfo.FieldType, (ParameterAttribute)attr); } } if (last != null) { RegisterParameter(last); } } // Add properties with ParameterAttribute foreach (PropertyInfo propertyInfo in cmdletType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { System.Diagnostics.Debug.WriteLine(propertyInfo.ToString()); object[] attributes = propertyInfo.GetCustomAttributes(false); // Get info for the setter and getter MethodInfo getter = propertyInfo.GetAccessors().FirstOrDefault(i => i.IsSpecialName && i.Name.StartsWith("get_")); MethodInfo setter = propertyInfo.GetSetMethod(); // Find all [Parameter] attributes on the property CommandParameterInfo last = null; ParameterAttribute paramAttr = null; foreach (object attr in attributes) { if (attr is ParameterAttribute) { paramAttr = (ParameterAttribute)attr; // if ValueFromPipeline or ValueFromPipelineByPropertyName is specified the property must have a public getter if ((paramAttr.ValueFromPipeline || paramAttr.ValueFromPipelineByPropertyName) && (getter == null || !getter.IsPublic)) { break; } // The property must have a public setter if (setter == null || !setter.IsPublic) { break; } last = AddParameterToParameterSet(paramSets, propertyInfo, propertyInfo.PropertyType, paramAttr); } } if (last != null) { RegisterParameter(last); } } // Clean the UniqueSetParameters foreach (var cur in UniqueSetParameters.Where(keyValue => (keyValue.Value == null)).ToList()) { UniqueSetParameters.Remove(cur.Key); } // Create param-sets collection Collection <CommandParameterSetInfo> paramSetInfo = new Collection <CommandParameterSetInfo>(); foreach (string paramSetName in paramSets.Keys) { bool bIsDefaultParamSet = paramSetName.Equals(strDefaultParameterSetName); paramSetInfo.Add(new CommandParameterSetInfo(paramSetName, bIsDefaultParamSet, paramSets[paramSetName])); // If a parameter set is not specified for a parmeter, then the parameter belongs to all the parameter sets, // therefore if this is not the AllParameterSets Set then add all parameters from the AllParameterSets Set to it... if (string.Compare(paramSetName, ParameterAttribute.AllParameterSets) != 0 && paramSets.ContainsKey(ParameterAttribute.AllParameterSets)) { foreach (CommandParameterInfo cpi in paramSets[ParameterAttribute.AllParameterSets]) { paramSets[paramSetName].Add(cpi); } } } ParameterSets = new ReadOnlyCollection <CommandParameterSetInfo>(paramSetInfo); }
private void AddParameterToParameterSet(Dictionary<string, Collection<CommandParameterInfo>> paramSets, CommandParameterInfo paramInfo) { var paramSetName = paramInfo.ParameterSetName; // create the parameter set if it doesn't exist, yet if (!paramSets.ContainsKey(paramSetName)) { paramSets.Add(paramSetName, new Collection<CommandParameterInfo>()); } Collection<CommandParameterInfo> paramSet = paramSets[paramSetName]; // actually add parameter to the set paramSet.Add(paramInfo); }
internal void Add(CommandParameterInfo info) { _parameters.Add(info); }
// internals //internal CmdletInfo CreateGetCommandCopy(CmdletInfo cmdletInfo, object[] arguments); //internal object[] Arguments { set; get; } //internal string FullName { get; } //internal bool IsGetCommandCopy { set; get; } /// <remarks> /// From MSDN article: http://msdn2.microsoft.com/en-us/library/ms714348(VS.85).aspx /// /// * A cmdlet can have any number of parameters. However, for a better user experience the number /// of parameters should be limited when possible. /// * Parameters must be declared on public non-static fields or properties. It is preferred for /// parameters to be declared on properties. The property must have a public setter, and if ValueFromPipeline /// or ValueFromPipelineByPropertyName is specified the property must have a public getter. /// * When specifying positional parameters, note the following. /// * Limit the number of positional parameters in a parameter set to less than five if possible. /// * Positional parameters do not have to be sequential; positions 5, 100, 250 works the same as positions 0, 1, 2. /// * When the Position keyword is not specified, the cmdlet parameter must be referenced by its name. /// * When using parameter sets, no parameter set should contain more than one positional parameter with the same position. /// * In addition, only one parameter in a set should declare ValueFromPipeline = true. Multiple parameters may define ValueFromPipelineByPropertyName = true. /// /// </remarks> private static ReadOnlyCollection<CommandParameterSetInfo> GetParameterSetInfo(Type cmdletType) { Dictionary<string, Collection<CommandParameterInfo>> paramSets = new Dictionary<string, Collection<CommandParameterInfo>>(StringComparer.CurrentCultureIgnoreCase); // TODO: Ensure there are no duplicate named or aliased parameters inside scope of a single parameter set. // TODO: When using parameter sets, no parameter set should contain more than one positional parameter with the same position. // TODO: If not parameters have a position declared then positions for all the parameters should be automatically declaredin the order they are specified // TODO: Only one parameter in a set should declare ValueFromRemainingArguments = true // TODO: Only one parameter in a set should declare ValueFromPipeline = true. Multiple parameters may define ValueFromPipelineByPropertyName = true. // TODO: Currently due to the way parameters are loaded into sets from all set at the end the parameter end up in incorrect order. // Add fields with ParameterAttribute foreach (FieldInfo filedInfo in cmdletType.GetFields(BindingFlags.Public | BindingFlags.Instance)) { System.Diagnostics.Debug.WriteLine(filedInfo.ToString()); object[] attributes = filedInfo.GetCustomAttributes(false); // Find all [Parameter] attributes on the property ParameterAttribute paramAttr = null; foreach (object attr in attributes) { if (attr is ParameterAttribute) { paramAttr = (ParameterAttribute)attr; CommandParameterInfo pi = new CommandParameterInfo(filedInfo, filedInfo.FieldType, paramAttr); string paramSetName = paramAttr.ParameterSetName ?? ParameterAttribute.AllParameterSets; if (!paramSets.ContainsKey(paramSetName)) { paramSets.Add(paramSetName, new Collection<CommandParameterInfo>()); } Collection<CommandParameterInfo> paramSet = paramSets[paramSetName]; paramSet.Add(pi); } } } // Add properties with ParameterAttribute foreach (PropertyInfo filedInfo in cmdletType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { System.Diagnostics.Debug.WriteLine(filedInfo.ToString()); object[] attributes = filedInfo.GetCustomAttributes(false); // Get info for the setter and getter MethodInfo getter = filedInfo.GetAccessors().FirstOrDefault(i => i.IsSpecialName && i.Name.StartsWith("get_")); MethodInfo setter = filedInfo.GetSetMethod(); // Find all [Parameter] attributes on the property ParameterAttribute paramAttr = null; foreach (object attr in attributes) { if (attr is ParameterAttribute) { paramAttr = (ParameterAttribute)attr; // if ValueFromPipeline or ValueFromPipelineByPropertyName is specified the property must have a public getter if ((paramAttr.ValueFromPipeline || paramAttr.ValueFromPipelineByPropertyName) && (getter == null || !getter.IsPublic)) { break; } // The property must have a public setter if (setter == null || !setter.IsPublic) { break; } CommandParameterInfo pi = new CommandParameterInfo(filedInfo, filedInfo.PropertyType, paramAttr); string paramSetName = paramAttr.ParameterSetName ?? ParameterAttribute.AllParameterSets; if (!paramSets.ContainsKey(paramSetName)) { paramSets.Add(paramSetName, new Collection<CommandParameterInfo>()); } Collection<CommandParameterInfo> paramSet = paramSets[paramSetName]; paramSet.Add(pi); } } } // Create param-sets collection Collection<CommandParameterSetInfo> paramSetInfo = new Collection<CommandParameterSetInfo>(); // TODO: find the name of the default param set string strDefaultParameterSetName = ParameterAttribute.AllParameterSets; object[] cmdLetAttrs = cmdletType.GetCustomAttributes(typeof(CmdletAttribute), false); if (cmdLetAttrs.Length > 0) strDefaultParameterSetName = ((CmdletAttribute)cmdLetAttrs[0]).DefaultParameterSetName ?? strDefaultParameterSetName; foreach (string paramSetName in paramSets.Keys) { bool bIsDefaultParamSet = paramSetName == strDefaultParameterSetName; paramSetInfo.Add(new CommandParameterSetInfo(paramSetName, bIsDefaultParamSet, paramSets[paramSetName])); // If a parameter set is not specified for a parmeter, then the parameter belongs to all the parameter sets, // therefore if this is not the AllParameterSets Set then add all parameters from the AllParameterSets Set to it... if (string.Compare(paramSetName, ParameterAttribute.AllParameterSets) != 0 && paramSets.ContainsKey(ParameterAttribute.AllParameterSets)) { foreach (CommandParameterInfo cpi in paramSets[ParameterAttribute.AllParameterSets]) { paramSets[paramSetName].Add(cpi); } } } return new ReadOnlyCollection<CommandParameterSetInfo>(paramSetInfo); }
// internals //internal CmdletInfo CreateGetCommandCopy(CmdletInfo cmdletInfo, object[] arguments); //internal object[] Arguments { set; get; } //internal string FullName { get; } //internal bool IsGetCommandCopy { set; get; } private CommandParameterInfo AddParameterToParameterSet(Dictionary<string, Collection<CommandParameterInfo>> paramSets, MemberInfo memberInfo, Type type, ParameterAttribute paramAttr) { CommandParameterInfo pi = new CommandParameterInfo(memberInfo, type, paramAttr); var paramSetName = paramAttr.ParameterSetName; // Determine if this parameter is uniquely defined for one set and rember it paramSetName = paramSetName ?? ParameterAttribute.AllParameterSets; if (!paramSets.ContainsKey(paramSetName)) { paramSets.Add(paramSetName, new Collection<CommandParameterInfo>()); } Collection<CommandParameterInfo> paramSet = paramSets[paramSetName]; paramSet.Add(pi); return pi; }
private void RegisterParameter(CommandParameterInfo parameterInfo) { // also add it to lookuptable and check for unuque names/aliases var allNames = parameterInfo.Aliases.ToList(); allNames.Add(parameterInfo.Name); foreach (var curName in allNames) { if (ParameterInfoLookupTable.ContainsKey(curName)) { // save exception to be thrown when this object is validated, not now var msg = String.Format("The name or alias '{0}' is used multiple times.", curName); _validationException = new MetadataException(msg); continue; } ParameterInfoLookupTable[curName] = parameterInfo; } }
// internals //internal CmdletInfo CreateGetCommandCopy(CmdletInfo cmdletInfo, object[] arguments); //internal object[] Arguments { set; get; } //internal string FullName { get; } //internal bool IsGetCommandCopy { set; get; } /// <remarks> /// From MSDN article: http://msdn2.microsoft.com/en-us/library/ms714348(VS.85).aspx /// /// * A cmdlet can have any number of parameters. However, for a better user experience the number /// of parameters should be limited when possible. /// * Parameters must be declared on public non-static fields or properties. It is preferred for /// parameters to be declared on properties. The property must have a public setter, and if ValueFromPipeline /// or ValueFromPipelineByPropertyName is specified the property must have a public getter. /// * When specifying positional parameters, note the following. /// * Limit the number of positional parameters in a parameter set to less than five if possible. /// * Positional parameters do not have to be sequential; positions 5, 100, 250 works the same as positions 0, 1, 2. /// * When the Position keyword is not specified, the cmdlet parameter must be referenced by its name. /// * When using parameter sets, no parameter set should contain more than one positional parameter with the same position. /// * In addition, only one parameter in a set should declare ValueFromPipeline = true. Multiple parameters may define ValueFromPipelineByPropertyName = true. /// /// </remarks> private static ReadOnlyCollection <CommandParameterSetInfo> GetParameterSetInfo(Type cmdletType) { Dictionary <string, Collection <CommandParameterInfo> > paramSets = new Dictionary <string, Collection <CommandParameterInfo> >(StringComparer.CurrentCultureIgnoreCase); // TODO: Ensure there are no duplicate named or aliased parameters inside scope of a single parameter set. // TODO: When using parameter sets, no parameter set should contain more than one positional parameter with the same position. // TODO: If not parameters have a position declared then positions for all the parameters should be automatically declaredin the order they are specified // TODO: Only one parameter in a set should declare ValueFromRemainingArguments = true // TODO: Only one parameter in a set should declare ValueFromPipeline = true. Multiple parameters may define ValueFromPipelineByPropertyName = true. // TODO: Currently due to the way parameters are loaded into sets from all set at the end the parameter end up in incorrect order. // Add fields with ParameterAttribute foreach (FieldInfo filedInfo in cmdletType.GetFields(BindingFlags.Public | BindingFlags.Instance)) { System.Diagnostics.Debug.WriteLine(filedInfo.ToString()); object[] attributes = filedInfo.GetCustomAttributes(false); // Find all [Parameter] attributes on the property ParameterAttribute paramAttr = null; foreach (object attr in attributes) { if (attr is ParameterAttribute) { paramAttr = (ParameterAttribute)attr; CommandParameterInfo pi = new CommandParameterInfo(filedInfo, filedInfo.FieldType, paramAttr); string paramSetName = paramAttr.ParameterSetName ?? ParameterAttribute.AllParameterSets; if (!paramSets.ContainsKey(paramSetName)) { paramSets.Add(paramSetName, new Collection <CommandParameterInfo>()); } Collection <CommandParameterInfo> paramSet = paramSets[paramSetName]; paramSet.Add(pi); } } } // Add properties with ParameterAttribute foreach (PropertyInfo filedInfo in cmdletType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { System.Diagnostics.Debug.WriteLine(filedInfo.ToString()); object[] attributes = filedInfo.GetCustomAttributes(false); // Get info for the setter and getter MethodInfo getter = filedInfo.GetAccessors().FirstOrDefault(i => i.IsSpecialName && i.Name.StartsWith("get_")); MethodInfo setter = filedInfo.GetSetMethod(); // Find all [Parameter] attributes on the property ParameterAttribute paramAttr = null; foreach (object attr in attributes) { if (attr is ParameterAttribute) { paramAttr = (ParameterAttribute)attr; // if ValueFromPipeline or ValueFromPipelineByPropertyName is specified the property must have a public getter if ((paramAttr.ValueFromPipeline || paramAttr.ValueFromPipelineByPropertyName) && (getter == null || !getter.IsPublic)) { break; } // The property must have a public setter if (setter == null || !setter.IsPublic) { break; } CommandParameterInfo pi = new CommandParameterInfo(filedInfo, filedInfo.PropertyType, paramAttr); string paramSetName = paramAttr.ParameterSetName ?? ParameterAttribute.AllParameterSets; if (!paramSets.ContainsKey(paramSetName)) { paramSets.Add(paramSetName, new Collection <CommandParameterInfo>()); } Collection <CommandParameterInfo> paramSet = paramSets[paramSetName]; paramSet.Add(pi); } } } // Create param-sets collection Collection <CommandParameterSetInfo> paramSetInfo = new Collection <CommandParameterSetInfo>(); // TODO: find the name of the default param set string strDefaultParameterSetName = ParameterAttribute.AllParameterSets; object[] cmdLetAttrs = cmdletType.GetCustomAttributes(typeof(CmdletAttribute), false); if (cmdLetAttrs.Length > 0) { strDefaultParameterSetName = ((CmdletAttribute)cmdLetAttrs[0]).DefaultParameterSetName ?? strDefaultParameterSetName; } foreach (string paramSetName in paramSets.Keys) { bool bIsDefaultParamSet = paramSetName == strDefaultParameterSetName; paramSetInfo.Add(new CommandParameterSetInfo(paramSetName, bIsDefaultParamSet, paramSets[paramSetName])); // If a parameter set is not specified for a parmeter, then the parameter belongs to all the parameter sets, // therefore if this is not the AllParameterSets Set then add all parameters from the AllParameterSets Set to it... if (string.Compare(paramSetName, ParameterAttribute.AllParameterSets) != 0 && paramSets.ContainsKey(ParameterAttribute.AllParameterSets)) { foreach (CommandParameterInfo cpi in paramSets[ParameterAttribute.AllParameterSets]) { paramSets[paramSetName].Add(cpi); } } } return(new ReadOnlyCollection <CommandParameterSetInfo>(paramSetInfo)); }
internal bool Contains(CommandParameterInfo param) { return Parameters.Contains(param); }
private static void AppendFormatCommandParameterInfo(CommandParameterInfo parameter, ref Text.StringBuilder result) { if (result.Length > 0) { // Add a space between parameters result.Append(" "); } if (parameter.ParameterType == typeof(SwitchParameter)) { result.AppendFormat(CultureInfo.InvariantCulture, parameter.IsMandatory ? "-{0}" : "[-{0}]", parameter.Name); } else { string parameterTypeString = GetParameterTypeString(parameter.ParameterType, parameter.Attributes); if (parameter.IsMandatory) { result.AppendFormat(CultureInfo.InvariantCulture, parameter.Position != int.MinValue ? "[-{0}] <{1}>" : "-{0} <{1}>", parameter.Name, parameterTypeString); } else { result.AppendFormat(CultureInfo.InvariantCulture, parameter.Position != int.MinValue ? "[[-{0}] <{1}>]" : "[-{0} <{1}>]", parameter.Name, parameterTypeString); } } }
/// <summary> /// /// </summary> /// <param name="obj"></param> /// <remarks> /// All abount Cmdlet parameters: http://msdn2.microsoft.com/en-us/library/ms714433(VS.85).aspx /// </remarks> internal override void BindArguments(PSObject obj) { // TODO: Bind obj properties to ValueFromPipelinebyPropertyName parameters // TODO: If parameter has ValueFromRemainingArguments any unmatched arguments should be bound to this parameter as an array // TODO: If no parameter has ValueFromRemainingArguments any supplied parameters are unmatched then fail with exception if ((obj == null) && (Parameters.Count == 0)) { return; } // TODO: Perform analysis on passed arguments and obj to identify which parameter set to select for binding CommandParameterSetInfo paramSetInfo = _cmdletInfo.GetDefaultParameterSet(); if (obj != null) { var valueFromPipelineParameter = paramSetInfo.Parameters.Where(paramInfo => paramInfo.ValueFromPipeline).SingleOrDefault(); if (valueFromPipelineParameter != null) { BindArgument(valueFromPipelineParameter.Name, obj, valueFromPipelineParameter.ParameterType); } } if (Parameters.Count > 0) { // bind by position location for (int i = 0; i < Parameters.Count; i++) { CommandParameterInfo paramInfo = null; CommandParameter parameter = Parameters[i]; if (string.IsNullOrEmpty(parameter.Name)) { paramInfo = paramSetInfo.GetParameterByPosition(i); if (paramInfo != null) { BindArgument(paramInfo.Name, parameter.Value, paramInfo.ParameterType); } } else { paramInfo = paramSetInfo.LookupParameter(parameter.Name); if (paramInfo != null) { if (parameter.Value == null && paramInfo.ParameterType != typeof(SwitchParameter) && i < Parameters.Count - 1 && Parameters[i + 1].Name == null) { BindArgument(paramInfo.Name, Parameters[i + 1].Value, paramInfo.ParameterType); i++; } else { BindArgument(paramInfo.Name, parameter.Value, paramInfo.ParameterType); } } else { //TODO: Throw ParameterBindingException when implemented throw(new Exception("No parameter found matching '" + parameter.Name + "'")); } } } } }
/// <summary> /// /// </summary> /// <param name="obj"></param> /// <remarks> /// All abount Cmdlet parameters: http://msdn2.microsoft.com/en-us/library/ms714433(VS.85).aspx /// </remarks> internal override void BindArguments(PSObject obj) { if ((obj == null) && (Parameters.Count == 0)) { return; } // TODO: bind the arguments to the parameters CommandParameterSetInfo paramSetInfo = _cmdletInfo.GetDefaultParameterSet(); // TODO: refer to the Command._ParameterSetName for a param set name if (obj != null) { foreach (CommandParameterInfo paramInfo in paramSetInfo.Parameters) { if (paramInfo.ValueFromPipeline) { // TODO: extract this into a method PropertyInfo pi = Command.GetType().GetProperty(paramInfo.Name, paramInfo.ParameterType); pi.SetValue(Command, obj, null); } } } if (Parameters.Count > 0) { // bind by position location for (int i = 0; i < Parameters.Count; i++) { CommandParameterInfo paramInfo = null; CommandParameter parameter = Parameters[i]; if (string.IsNullOrEmpty(parameter.Name)) { paramInfo = paramSetInfo.GetParameterByPosition(i); if (paramInfo != null) { // TODO: extract this into a method PropertyInfo pi = Command.GetType().GetProperty(paramInfo.Name, paramInfo.ParameterType); // TODO: make this generic if (pi.PropertyType == typeof(PSObject[])) { PSObject[] arr = new PSObject[] { PSObject.AsPSObject(Parameters[i].Value) }; pi.SetValue(Command, arr, null); } else if (pi.PropertyType == typeof(String[])) { String[] arr = new String[] { Parameters[i].Value.ToString() }; pi.SetValue(Command, arr, null); } else { pi.SetValue(Command, Parameters[i].Value, null); } } } else { paramInfo = paramSetInfo.GetParameterByName(parameter.Name); if (paramInfo != null) { // TODO: extract this into a method PropertyInfo pi = Command.GetType().GetProperty(paramInfo.Name, paramInfo.ParameterType); pi.SetValue(Command, Parameters[i].Value, null); } } } } }
private void AddParameter(MemberInfo info, Type parameterType, ParameterAttribute paramAttribute) { var paramInfo = new CommandParameterInfo(info, parameterType, paramAttribute); if (!NamedParameters.ContainsKey(paramInfo.Name)) { NamedParameters[paramInfo.Name] = paramInfo; } AllParameters.Add(paramInfo); }
private void BindParameter(CommandParameterInfo info, object value, bool doConvert) { var memberInfo = info.MemberInfo; if (_boundParameters.Contains(memberInfo)) { var msg = String.Format("Parameter '{0}' has already been bound!", info.Name); throw new ParameterBindingException(msg); } // ConvertTo throws an exception if conversion isn't possible. That's just fine. if (doConvert) { value = LanguagePrimitives.ConvertTo(value, info.ParameterType); } // TODO: validate value with Attributes (ValidateNotNullOrEmpty, etc) SetCommandValue(memberInfo, value); _boundParameters.Add(memberInfo); }
internal ParameterBindingException(string message, string errorId, CommandParameterInfo target) : base(message, errorId, ErrorCategory.InvalidArgument, target) { ParameterName = target.Name; ParameterType = target.ParameterType; }
internal ParameterBindingException(string message, string errorId, CommandParameterInfo target) : base(message, errorId, ErrorCategory.InvalidArgument, target) { ParameterName = target.Name; ParameterType = target.ParameterType; }
/// <summary> /// Constructs an instance of a ParameterInfo object /// </summary> /// <param name="parameterInfo">Parameter info of the parameter</param> public ParameterInfo(CommandParameterInfo parameterInfo) { this.Name = "-" + parameterInfo.Name; this.ParameterType = parameterInfo.ParameterType.FullName; this.Position = parameterInfo.Position; this.IsMandatory = parameterInfo.IsMandatory; this.HelpMessage = parameterInfo.HelpMessage; }
private object GatherParameterValue(CommandParameterInfo param) { // TODO: implement asking the user for a value return null; }
// restricts the candidate parameter sets by the newly bound parameters private void RestrictCandidatesByBoundParameter(CommandParameterInfo info) { var setsContaining = from paramSet in _cmdletInfo.ParameterSets where paramSet.Contains(info) select paramSet; _candidateParameterSets = _candidateParameterSets.Intersect(setsContaining).ToList(); if (_candidateParameterSets.Count == 0) { ThrowAmbiguousParameterSetException(); } else if (_candidateParameterSets.Count == 1) { _activeSet = _candidateParameterSets[0]; } }
private void BindParameter(CommandParameterInfo info, object value, bool doConvert) { var memberInfo = info.MemberInfo; if (_boundParameters.Contains(memberInfo)) { var msg = String.Format("Parameter '{0}' has already been bound!", info.Name); throw new ParameterBindingException(msg); } foreach (var attr in info.TransformationAttributes) { value = attr.Transform(_engineIntrinsics, value); } // ConvertTo throws an exception if conversion isn't possible. That's just fine. if (doConvert) { value = LanguagePrimitives.ConvertTo(value, info.ParameterType); } // TODO: validate value with Attributes (ValidateNotNullOrEmpty, etc) SetCommandValue(memberInfo, value); // make sure to update the candidate set to only consider parameter sets with the newly bound parameter RestrictCandidatesByBoundParameter(info); _boundParameters.Add(memberInfo); }
private bool TryBindParameter(CommandParameterInfo info, object value, bool doConvert) { try { BindParameter(info, value, doConvert); return true; } catch (Exception) { return false; } }
// internals //internal CmdletInfo CreateGetCommandCopy(CmdletInfo cmdletInfo, object[] arguments); //internal object[] Arguments { set; get; } //internal string FullName { get; } //internal bool IsGetCommandCopy { set; get; } /// <remarks> /// From MSDN article: http://msdn2.microsoft.com/en-us/library/ms714348(VS.85).aspx /// /// * A cmdlet can have any number of parameters. However, for a better user experience the number /// of parameters should be limited when possible. /// * Parameters must be declared on public non-static fields or properties. It is preferred for /// parameters to be declared on properties. The property must have a public setter, and if ValueFromPipeline /// or ValueFromPipelineByPropertyName is specified the property must have a public getter. /// * When specifying positional parameters, note the following. /// * Limit the number of positional parameters in a parameter set to less than five if possible. /// * Positional parameters do not have to be sequential; positions 5, 100, 250 works the same as positions 0, 1, 2. /// * When the Position keyword is not specified, the cmdlet parameter must be referenced by its name. /// * When using parameter sets, no parameter set should contain more than one positional parameter with the same position. /// * In addition, only one parameter in a set should declare ValueFromPipeline = true. Multiple parameters may define ValueFromPipelineByPropertyName = true. /// /// </remarks> private static ReadOnlyCollection <CommandParameterSetInfo> GetParameterSetInfo(Type cmdletType) { Dictionary <string, Collection <CommandParameterInfo> > paramSets = new Dictionary <string, Collection <CommandParameterInfo> >(StringComparer.CurrentCultureIgnoreCase); // Extract all the public parameters from the Cmdlet /* TODO: gather all the field parameters * foreach(var filedInfo in cmdletType.GetFields(BindingFlags.Public | BindingFlags.Instance)) * { * System.Diagnostics.Debug.WriteLine(filedInfo.ToString()); * } */ foreach (PropertyInfo filedInfo in cmdletType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { System.Diagnostics.Debug.WriteLine(filedInfo.ToString()); object[] attributes = filedInfo.GetCustomAttributes(false); // Find if there are any [Parameter] attributes on the property ParameterAttribute paramAttr = null; foreach (object attr in attributes) { if (attr is ParameterAttribute) { paramAttr = (ParameterAttribute)attr; break; } } // TODO: make sure that the PropertyInfo.GetAccessors() returns the appropriate set of accessors if (paramAttr != null) { CommandParameterInfo pi = new CommandParameterInfo(filedInfo.Name, filedInfo.PropertyType, paramAttr); string paramSetName = paramAttr.ParameterSetName ?? ParameterAttribute.AllParameterSets; if (!paramSets.ContainsKey(paramSetName)) { paramSets.Add(paramSetName, new Collection <CommandParameterInfo>()); } Collection <CommandParameterInfo> paramSet = paramSets[paramSetName]; paramSet.Add(pi); } } // Create param-sets collection Collection <CommandParameterSetInfo> paramSetInfo = new Collection <CommandParameterSetInfo>(); // TODO: find the name of the default param set string strDefaultParameterSetName = ParameterAttribute.AllParameterSets; object[] cmdLetAttrs = cmdletType.GetCustomAttributes(typeof(CmdletAttribute), false); if (cmdLetAttrs.Length > 0) { strDefaultParameterSetName = ((CmdletAttribute)cmdLetAttrs[0]).DefaultParameterSetName ?? strDefaultParameterSetName; } foreach (string paramSetName in paramSets.Keys) { bool bIsDefaultParamSet = paramSetName == strDefaultParameterSetName; paramSetInfo.Add(new CommandParameterSetInfo(paramSetName, bIsDefaultParamSet, paramSets[paramSetName])); } return(new ReadOnlyCollection <CommandParameterSetInfo>(paramSetInfo)); }
// internals //internal CmdletInfo CreateGetCommandCopy(CmdletInfo cmdletInfo, object[] arguments); //internal object[] Arguments { set; get; } //internal string FullName { get; } //internal bool IsGetCommandCopy { set; get; } /// <remarks> /// From MSDN article: http://msdn2.microsoft.com/en-us/library/ms714348(VS.85).aspx /// /// * A cmdlet can have any number of parameters. However, for a better user experience the number /// of parameters should be limited when possible. /// * Parameters must be declared on public non-static fields or properties. It is preferred for /// parameters to be declared on properties. The property must have a public setter, and if ValueFromPipeline /// or ValueFromPipelineByPropertyName is specified the property must have a public getter. /// * When specifying positional parameters, note the following. /// * Limit the number of positional parameters in a parameter set to less than five if possible. /// * Positional parameters do not have to be sequential; positions 5, 100, 250 works the same as positions 0, 1, 2. /// * When the Position keyword is not specified, the cmdlet parameter must be referenced by its name. /// * When using parameter sets, no parameter set should contain more than one positional parameter with the same position. /// * In addition, only one parameter in a set should declare ValueFromPipeline = true. Multiple parameters may define ValueFromPipelineByPropertyName = true. /// /// </remarks> private static ReadOnlyCollection<CommandParameterSetInfo> GetParameterSetInfo(Type cmdletType) { Dictionary<string, Collection<CommandParameterInfo>> paramSets = new Dictionary<string, Collection<CommandParameterInfo>>(StringComparer.CurrentCultureIgnoreCase); // Extract all the public parameters from the Cmdlet /* TODO: gather all the field parameters foreach(var filedInfo in cmdletType.GetFields(BindingFlags.Public | BindingFlags.Instance)) { System.Diagnostics.Debug.WriteLine(filedInfo.ToString()); } */ foreach (PropertyInfo filedInfo in cmdletType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { System.Diagnostics.Debug.WriteLine(filedInfo.ToString()); object[] attributes = filedInfo.GetCustomAttributes(false); // Find if there are any [Parameter] attributes on the property ParameterAttribute paramAttr = null; foreach (object attr in attributes) { if (attr is ParameterAttribute) { paramAttr = (ParameterAttribute) attr; break; } } // TODO: make sure that the PropertyInfo.GetAccessors() returns the appropriate set of accessors if (paramAttr != null) { CommandParameterInfo pi = new CommandParameterInfo(filedInfo.Name, filedInfo.PropertyType, paramAttr); string paramSetName = paramAttr.ParameterSetName ?? ParameterAttribute.AllParameterSets; if (!paramSets.ContainsKey(paramSetName)) { paramSets.Add(paramSetName, new Collection<CommandParameterInfo>()); } Collection<CommandParameterInfo> paramSet = paramSets[paramSetName]; paramSet.Add(pi); } } // Create param-sets collection Collection<CommandParameterSetInfo> paramSetInfo = new Collection<CommandParameterSetInfo>(); // TODO: find the name of the default param set string strDefaultParameterSetName = ParameterAttribute.AllParameterSets; object[] cmdLetAttrs = cmdletType.GetCustomAttributes(typeof (CmdletAttribute), false); if (cmdLetAttrs.Length > 0) strDefaultParameterSetName = ((CmdletAttribute)cmdLetAttrs[0]).DefaultParameterSetName ?? strDefaultParameterSetName; foreach(string paramSetName in paramSets.Keys) { bool bIsDefaultParamSet = paramSetName == strDefaultParameterSetName; paramSetInfo.Add(new CommandParameterSetInfo(paramSetName, bIsDefaultParamSet, paramSets[paramSetName])); } return new ReadOnlyCollection<CommandParameterSetInfo>(paramSetInfo); }
// internals //internal CmdletInfo CreateGetCommandCopy(CmdletInfo cmdletInfo, object[] arguments); //internal object[] Arguments { set; get; } //internal string FullName { get; } //internal bool IsGetCommandCopy { set; get; } private CommandParameterInfo AddParameterToParameterSet(Dictionary<string, Collection<CommandParameterInfo>> paramSets, MemberInfo memberInfo, Type type, ParameterAttribute paramAttr) { CommandParameterInfo pi = new CommandParameterInfo(memberInfo, type, paramAttr); var paramSetName = paramAttr.ParameterSetName; // Determine if this parameter is uniquely defined for one set and rember it if (!String.IsNullOrEmpty(paramSetName) && !paramSetName.Equals(ParameterAttribute.AllParameterSets)) { var parameterName = pi.Name; // check if we already defined that parameter for another set if (UniqueSetParameters.ContainsKey(parameterName)) { UniqueSetParameters[parameterName] = null; } else { // not yet in any set, it's a candidate for a unique parameter UniqueSetParameters[parameterName] = paramSetName; } } paramSetName = paramSetName ?? ParameterAttribute.AllParameterSets; if (!paramSets.ContainsKey(paramSetName)) { paramSets.Add(paramSetName, new Collection<CommandParameterInfo>()); } Collection<CommandParameterInfo> paramSet = paramSets[paramSetName]; paramSet.Add(pi); return pi; }
internal bool Contains(CommandParameterInfo param) { return(Parameters.Contains(param)); }
private object GatherParameterValue(CommandParameterInfo param) { // TODO: implement asking the user for a value return(null); }