Example #1
0
 public void WriteObject(object sendToPipeline)
 {
     // AutomationNull.Value is never written to stream, it's like "void"
     if (sendToPipeline == AutomationNull.Value)
     {
         return;
     }
     OutputStream.Write(PSObject.WrapOrNull(sendToPipeline));
 }
Example #2
0
        /// <summary>
        /// Convert between types.
        /// </summary>
        /// <param name="valueToConvert">The value to convert.</param>
        /// <param name="resultType">The type you want to convert to.</param>
        /// <param name="formatProvider">The format provider to use for type conversions.</param>
        /// <returns>The converted type.</returns>
        public static object ConvertTo(object valueToConvert, Type resultType, IFormatProvider formatProvider)
        {
            // TODO: Make it use formatProvider
            // TODO: read more about the Extended Type System (ETS) of Powershell and enhance this functionality
            // TODO: check "3.7.5 Better conversion" of Windows Powershell Language Specification 3.0
            if (resultType == null)
            {
                throw new ArgumentException("Result type can not be null.");
            }

            // if it's a cast to void, we want to "mute" the output. That's done by converting to null
            if (resultType == typeof(void))
            {
                return(AutomationNull.Value);
            }

            // result is no PSObject, so unpack the value if we deal with one
            if (valueToConvert is PSObject &&
                resultType != typeof(PSObject) &&
                resultType != typeof(PSObject[]))
            {
                valueToConvert = ((PSObject)valueToConvert).BaseObject;
            }

            // check if the result is an array and we have something that needs to be casted
            if (resultType.IsArray && valueToConvert != null && resultType != valueToConvert.GetType())
            {
                var elementType = resultType.GetElementType();

                if (elementType == typeof(char) && valueToConvert is string)
                {
                    return(((string)valueToConvert).ToCharArray());
                }

                var enumerableValue = GetEnumerable(valueToConvert);
                // check for simple packaging
                // Powershell seems to neither enumerate dictionaries nor strings
                if (enumerableValue == null)
                {
                    var array = Array.CreateInstance(elementType, 1);
                    array.SetValue(ConvertTo(valueToConvert, elementType, formatProvider), 0);
                    return(array);
                }

                // otherwise we have some IEnumerable thing. recursively create a list and copy to array
                // a list first, because we don't know the number of arguments
                var list = (IList)Activator.CreateInstance(typeof(List <>).MakeGenericType(elementType));
                foreach (var curValue in enumerableValue)
                {
                    list.Add(ConvertTo(curValue, elementType, formatProvider));
                }
                var targetArray = Array.CreateInstance(elementType, list.Count);
                for (int i = 0; i < list.Count; i++)
                {
                    targetArray.SetValue(list[i], i);
                }
                return(targetArray);
            }

            // resultType is no array
            // TODO: use PSTypeConverters for the following!
            if (resultType == typeof(PSObject))
            {
                return(PSObject.WrapOrNull(valueToConvert));
            }

            if (valueToConvert != null && resultType.IsAssignableFrom(valueToConvert.GetType()))
            {
                return(valueToConvert);
            }

            if (resultType == typeof(char))
            {
                return(ConvertToChar(valueToConvert));
            }

            if (resultType == typeof(string))
            {
                return(ConvertToString(valueToConvert, formatProvider));
            }

            if (resultType == typeof(XmlDocument))
            {
                var doc = new XmlDocument();
                doc.LoadXml(ConvertTo <string>(valueToConvert));
                return(doc);
            }

            if (resultType == typeof(Regex))
            {
                return(new Regex(ConvertTo <string>(valueToConvert)));
            }

            if (resultType == typeof(bool))
            {
                return(ConvertToBool(valueToConvert));
            }

            if (valueToConvert != null && resultType.IsEnum) // enums have to be parsed
            {
                return(Enum.Parse(resultType, valueToConvert.ToString(), true));
            }

            if (resultType.IsNumeric())
            {
                try
                {
                    return(ConvertToNumeric(valueToConvert, resultType));
                }
                catch (Exception)
                {
                    throw new PSInvalidCastException(String.Format("Couldn't convert from '{0}' to numeric type",
                                                                   valueToConvert.ToString()));
                }
            }

            if (resultType == typeof(SwitchParameter))
            {
                if (valueToConvert == null)
                {
                    return(new SwitchParameter(false));
                }
                else if (valueToConvert is bool)
                {
                    return(new SwitchParameter((bool)valueToConvert));
                }
            }

            object result = null;

            if (valueToConvert != null && TryConvertUsingTypeConverter(valueToConvert, resultType, out result))
            {
                return(result);
            }

            if (valueToConvert != null && TryConvertWithConstructor(valueToConvert, resultType, out result))
            {
                return(result);
            }

            /* TODO: further conversion methods:
             * Parse Method: If the source type is string and the destination type has a method called Parse, that
             * method is called to perform the conversion.
             * Constructors: If the destination type has a constructor taking a single argument whose type is that of
             * the source type, that constructor is called to perform the conversion.
             */
            return(DefaultConvertOrCast(valueToConvert, resultType));
        }
Example #3
0
 public void WriteObject(object sendToPipeline)
 {
     OutputStream.Write(PSObject.WrapOrNull(sendToPipeline));
 }