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)); }
/// <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)); }
public void WriteObject(object sendToPipeline) { OutputStream.Write(PSObject.WrapOrNull(sendToPipeline)); }