Example #1
0
        // 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);
        }
Example #2
0
        /// <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);
        }