Streamfab.keepstreams.generic.hook-smeagol-ther... -
var inner = provider.GetRequiredService<FileStream>(); var factory = provider.GetRequiredService<IHookFactory<MyCustomHook>>(); return new HookSmeagol<MyCustomHook>(inner, factory.Create(provider)); ); HookSmeagol can be stacked :
// 2. The inner stream performs the real read int bytesRead = _inner.Read(buffer, offset, count); StreamFab.KeepStreams.Generic.Hook-Smeagol-TheR...
// 3. Post‑hook (e.g., logging, decryption, metrics) await _hook.AfterReadAsync(_ctx, destination.Slice(0, bytesRead), cancellationToken) .ConfigureAwait(false); var inner = provider
public sealed class LoggingHook : IStreamHook { public void BeforeRead(IHookContext ctx, byte[] buffer, int offset, int count) => Console.WriteLine($"[LOG] About to read var inner = provider.GetRequiredService<
public void Dispose(IHookContext ctx) /* free any unmanaged resources */
| Event name | Payload | |------------|---------| | ReadStart | StreamId, Count, Timestamp | | ReadStop | StreamId, BytesRead, ElapsedMs | | WriteStart | StreamId, Count, Timestamp | | WriteStop | StreamId, BytesWritten, ElapsedMs | | Error | StreamId, Exception, Operation |
The pattern mirrors Read ; the hook receives the buffer before the inner write and again after the write completes. 3.4 Seek , SetLength , Flush All these methods follow the same pre‑hook → inner operation → post‑hook flow. The async variants are implemented using ValueTask when possible to avoid allocations. 3.5 Disposal protected override void Dispose(bool disposing)