/// <summary>
        /// Helper method to do additional transformation on the output value.
        /// </summary>
        internal static object TransformOutBindingValueAsNeeded(string bindingName, ReadOnlyBindingInfo bindingInfo, object value)
        {
            switch (bindingInfo.Type)
            {
            case "http":
                // Try converting the value to HttpResponseContext if it's not already an object of such type.
                if (value is HttpResponseContext)
                {
                    break;
                }

                try
                {
                    value = LanguagePrimitives.ConvertTo <HttpResponseContext>(value);
                }
                catch (PSInvalidCastException ex)
                {
                    string errorMsg = string.Format(PowerShellWorkerStrings.FailToConvertToHttpResponseContext, bindingName, ex.Message);
                    throw new InvalidOperationException(errorMsg);
                }

                break;

            default:
                break;
            }

            return(value);
        }
        /// <summary>
        /// Helper private function that maps an output binding to a data collecting behavior.
        /// </summary>
        private DataCollectingBehavior GetDataCollectingBehavior(ReadOnlyBindingInfo bindingInfo)
        {
            switch (bindingInfo.Type)
            {
            case "http": return(DataCollectingBehavior.Singleton);

            case "blob": return(DataCollectingBehavior.Singleton);

            case "sendGrid": return(DataCollectingBehavior.Singleton);

            case "onedrive": return(DataCollectingBehavior.Singleton);

            case "outlook":  return(DataCollectingBehavior.Singleton);

            case "notificationHub": return(DataCollectingBehavior.Singleton);

            case "excel": return(DataCollectingBehavior.Collection);

            case "table": return(DataCollectingBehavior.Collection);

            case "queue": return(DataCollectingBehavior.Collection);

            case "eventHub": return(DataCollectingBehavior.Collection);

            case "documentDB":  return(DataCollectingBehavior.Collection);

            case "mobileTable": return(DataCollectingBehavior.Collection);

            case "serviceBus":  return(DataCollectingBehavior.Collection);

            case "signalR":     return(DataCollectingBehavior.Collection);

            case "twilioSms":   return(DataCollectingBehavior.Collection);

            case "graphWebhookSubscription": return(DataCollectingBehavior.Collection);

            // Be conservative on new output bindings
            default: return(DataCollectingBehavior.Singleton);
            }
        }
        /// <summary>
        /// Helper method to do additional transformation on the input value based on the type constraints specified in the script.
        /// </summary>
        internal static object TransformInBindingValueAsNeeded(PSScriptParamInfo paramInfo, ReadOnlyBindingInfo bindingInfo, object value)
        {
            switch (bindingInfo.Type)
            {
            case "blob":
            case "blobTrigger":
                // For blob input, the input data could be an array of bytes or a string. Documentation says
                // that a user can specify the 'dataType' to make the input data of the expected type. (see
                // https://docs.microsoft.com/en-us/azure/azure-functions/functions-triggers-bindings#binding-datatype-property)
                //
                // However, I found this setting is somewhat broken:
                //  1. For the 'blobTrigger' type in-binding, the input data is always byte array and the host doesn't
                //     respect the "dataType" setting in 'function.json'.
                //  2. For the 'blob' type in-binding, the input data type is 'String' by default. When specified, the
                //    'binary' and 'string' dataType are respected, but 'stream' dataType is not respected.
                //
                // Due to (1), we should be reasonably smart and transform the data appropriately when type constraint is
                // specified on the input parameter to indicate the expected data type.
                Type paramType = paramInfo.ParamType;
                if (value is byte[] blobBytes)
                {
                    if (paramType == typeof(string))
                    {
                        // String is expected, so convert the byte array to string using UTF8 encoding.
                        // This is a best effort attempt, as we don't know the true encoding.
                        value = Encoding.UTF8.GetString(blobBytes);
                    }
                    else if (paramType == typeof(Stream))
                    {
                        // Stream is expected, so convert the byte array to a MemoryStream.
                        value = new MemoryStream(blobBytes);
                    }
                }

                // When the input is 'String', we don't attempt to convert it to bytes because if the blob
                // is in fact a binary file, it's impossible to get the right bytes back even if we use the
                // same encoding used by the host when converting those bytes to string.

                break;

            default:
                break;
            }

            return(value);
        }
 /// <summary>
 /// BeginProcessing override.
 /// </summary>
 protected override void BeginProcessing()
 {
     _bindingInfo    = GetBindingInfo(Name);
     _behavior       = GetDataCollectingBehavior(_bindingInfo);
     _outputBindings = FunctionMetadata.GetOutputBindingHashtable(Runspace.DefaultRunspace.InstanceId);
 }