public async Task InitAsync(Func <Task <Stream> > builder, Type userType, BindToStreamBindingProvider <TAttribute> parent, string invokeString)
            {
                Type           = userType;
                _invokeString  = invokeString;
                _streamBuilder = builder;
                _parent        = parent;

                _userValue = await this.CreateUserArgAsync();
            }
 public StreamBinding(
     AttributeCloner <TAttribute> cloner,
     ParameterDescriptor param,
     BindToStreamBindingProvider <TAttribute> parent,
     Type argHelper,
     Type userType,
     FileAccess targetFileAccess,
     object converterParam)
     : base(cloner, param)
 {
     _parent            = parent;
     _userType          = userType;
     _targetFileAccess  = targetFileAccess;
     _typeValueProvider = argHelper;
     _converter         = converterParam;
 }
            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);
            }