public static IBinding TryBuild()

in src/Microsoft.Azure.WebJobs.Host/Bindings/BindingProviders/BindToStreamBindingProvider.cs [282:406]


            public static IBinding TryBuild<TUserType>(
                BindToStreamBindingProvider<TAttribute> parent,
                BindingProviderContext context)
            {
                // Allowed Param types:
                //  Stream
                //  any T with a Stream --> T conversion 
                // out T, with a Out<Stream,T> --> void conversion 

                var parameter = context.Parameter;
                var parameterType = parameter.ParameterType;


                var attributeSource = TypeUtility.GetResolvedAttribute<TAttribute>(parameter);

                // Stream is either way; all other types are known. 
                FileAccess? declaredAccess = GetFileAccessFromAttribute(attributeSource);

                Type argHelperType;
                bool isRead;

                IConverterManager cm = parent._converterManager;
                INameResolver nm = parent._nameResolver;
                IConfiguration config = parent._configuration;

                object converterParam = null;
                {
                    if (parameter.IsOut)
                    {
                        var outConverter = cm.GetConverter<ApplyConversion<TUserType, Stream>, object, TAttribute>();
                        if (outConverter != null)
                        {
                            converterParam = outConverter;
                            isRead = false;
                            argHelperType = typeof(OutArgBaseValueProvider<>).MakeGenericType(typeof(TAttribute), typeof(TUserType));
                        }
                        else
                        {
                            throw new InvalidOperationException($"No stream converter to handle {typeof(TUserType).FullName}.");
                        }
                    }
                    else
                    {
                        var converter = cm.GetConverter<Stream, TUserType, TAttribute>();
                        if (converter != null)
                        {
                            converterParam = converter;

                            if (parameterType == typeof(Stream))
                            {
                                if (!declaredAccess.HasValue)
                                {
                                    throw new InvalidOperationException("When binding to Stream, the attribute must specify a FileAccess direction.");
                                }
                                switch (declaredAccess.Value)
                                {
                                    case FileAccess.Read:
                                        isRead = true;

                                        break;
                                    case FileAccess.Write:
                                        isRead = false;
                                        break;

                                    default:
                                        throw new NotImplementedException("ReadWrite access is not supported. Pick either Read or Write.");
                                }
                            }
                            else
                            {
                                // For backwards compat, we recognize TextWriter as write; 
                                // anything else should explicitly set the FileAccess flag. 
                                if (typeof(TextWriter).IsAssignableFrom(typeof(TUserType)))
                                {
                                    isRead = false;
                                }
                                else
                                {
                                    isRead = true;
                                }
                            }


                            argHelperType = typeof(ValueProvider<>).MakeGenericType(typeof(TAttribute), typeof(TUserType));
                        }
                        else
                        {
                            // This rule can't bind. 
                            // Let another try. 
                            context.BindingErrors.Add(String.Format(Resource.BindingAssemblyConflictMessage, typeof(Stream).AssemblyQualifiedName, typeof(TUserType).AssemblyQualifiedName));
                            return null;
                        }
                    }
                }

                VerifyAccessOrThrow(declaredAccess, isRead);
                if (!parent.IsSupportedByRule(isRead))
                {
                    return null;
                }

                var cloner = new AttributeCloner<TAttribute>(attributeSource, context.BindingDataContract, config, nm);

                ParameterDescriptor param;
                if (parent.BuildParameterDescriptor != null)
                {
                    param = parent.BuildParameterDescriptor(attributeSource, parameter, nm);
                }
                else
                {
                    param = new ParameterDescriptor
                    {
                        Name = parameter.Name,
                        DisplayHints = new ParameterDisplayHints
                        {
                            Description = isRead ? "Read Stream" : "Write Stream"
                        }
                    };
                }

                var fileAccess = isRead ? FileAccess.Read : FileAccess.Write;
                IBinding binding = new StreamBinding(cloner, param, parent, argHelperType, parameterType, fileAccess, converterParam);

                return binding;
            }