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); }