protected override void Dispose(bool disposing) { // this is necessary because CanRead/Write/Seek should return false for a closed stream this.capabilities = new StreamCapabilities { CanTimeout = this.CanTimeout }; base.Dispose(disposing); }
public TakeStream(Stream stream, long count, bool leaveOpen) : base(StreamCapabilities.InferFrom(stream).Intersect(ReadCapabilities), ReadCapabilities) { this.stream = stream; this.count = this.remaining = count; this.initialPosition = stream.CanSeek ? stream.Position : default(long?); this.leaveOpen = leaveOpen; }
protected StreamBase(StreamCapabilities currentCapabilities, StreamCapabilities typeCapabilities) { if (currentCapabilities.Except(typeCapabilities) != StreamCapabilities.None) { throw new ArgumentException(nameof(currentCapabilities) + " may not exceed " + nameof(typeCapabilities)); } VerifyCapabilities(this.GetType(), typeCapabilities); this.capabilities = currentCapabilities; }
private static void VerifyCapabilities(Type streamType, StreamCapabilities capabilities) { // safe because Hashtable is safe for multiple concurrent readers and one writer var cachedCapabilitiesObj = VerifiedTypeCache[streamType]; if (cachedCapabilitiesObj != null) { var cachedCapabilities = (StreamCapabilities)cachedCapabilitiesObj; if (cachedCapabilities != capabilities) { throw new ArgumentException($"{streamType} was previously validated for the following capabilities: {capabilities}. It cannot be revalidated for a different set of capabilities ({capabilities})"); } return; } var requiredMethods = new HashSet <MethodInfo>(); if (capabilities.CanSyncRead) { requiredMethods.Add(ReadMethod); } if (capabilities.CanAsyncRead) { requiredMethods.Add(ReadAsyncMethod); } if (capabilities.CanSyncWrite) { requiredMethods.Add(WriteMethod); requiredMethods.Add(FlushMethod); } if (capabilities.CanAsyncWrite) { requiredMethods.Add(WriteAsyncMethod); requiredMethods.Add(FlushAsyncMethod); } if (capabilities.CanGetLength) { requiredMethods.Add(GetLengthMethod); } if (capabilities.CanGetPosition) { requiredMethods.Add(GetPositionMethod); } if (capabilities.CanSeek) { if (capabilities.CanWrite) { requiredMethods.Add(SetLengthMethod); } requiredMethods.Add(SetPositionMethod); } if (capabilities.CanTimeout) { if (capabilities.CanRead) { requiredMethods.Add(ReadTimeoutProperty.GetMethod); requiredMethods.Add(ReadTimeoutProperty.SetMethod); } if (capabilities.CanWrite) { requiredMethods.Add(WriteTimeoutProperty.GetMethod); requiredMethods.Add(WriteTimeoutProperty.SetMethod); } } var potentialOverrides = new HashSet <MethodInfo>( streamType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .Where(m => m.DeclaringType != typeof(StreamBase)) ); var overrides = streamType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .Where(m => m.DeclaringType != typeof(StreamBase)) .Select(s => s.GetBaseDefinition()) .Where(OverridableMethods.Contains); foreach (var method in overrides) { if (!requiredMethods.Remove(method)) { throw new ArgumentException($"{streamType} override of method {method} does not match the specified capabilities"); } } if (requiredMethods.Count > 0) { var missingMethods = string.Join(", ", requiredMethods); throw new ArgumentException($"Type {streamType} is missing the following overrides that are required to implement the provided capabilities: {missingMethods}"); } lock (VerifiedTypeCache.SyncRoot) { VerifiedTypeCache[streamType] = null; } }
protected StreamBase(StreamCapabilities capabilities) { VerifyCapabilities(this.GetType(), capabilities); this.capabilities = capabilities; }
public AutoFlushedStream(Stream stream, bool leaveOpen) : base(StreamCapabilities.InferFrom(stream).Intersect(BaseCapabilities), BaseCapabilities) { this.stream = stream; this.leaveOpen = leaveOpen; }
public ConcatStream(Stream first, Stream second) : base(StreamCapabilities.InferFrom(first).Intersect(StreamCapabilities.InferFrom(second)).Intersect(ReadCapabilities), ReadCapabilities) { this.first = first; this.second = second; }