You can subscribe using:
public sealed class LoggingHook : IStreamHook { public void BeforeRead(IHookContext ctx, byte[] buffer, int offset, int count) => Console.WriteLine($"[LOG] About to read
return bytesRead;
// 3. Post‑hook (e.g., logging, decryption, metrics) await _hook.AfterReadAsync(_ctx, destination.Slice(0, bytesRead), cancellationToken) .ConfigureAwait(false);
if (disposing) // Hook gets notified first – it can release its own resources _hook.Dispose(_ctx); StreamFab.KeepStreams.Generic.Hook-Smeagol-TheR...
// 1. Pre‑hook (may adjust the requested length) _hook.BeforeReadAsync(_ctx, destination, cancellationToken);
// Then the inner stream is disposed (unless the hook says otherwise) _inner.Dispose(); base.Dispose(disposing); You can subscribe using: public sealed class LoggingHook
var encrypted = new HookSmeagol<EncryptionHook>(baseStream, encryptionHook); var logged = new HookSmeagol<LoggingHook>(encrypted, loggingHook); var throttled = new HookSmeagol<ThrottlingHook>(logged, throttlingHook); The order matters: the outermost hook sees data all inner hooks have processed it. In the example above, the logger records encrypted bytes, then the throttler sees the same encrypted payload. 6. Performance considerations | Aspect | Guidance | |--------|----------| | Allocation avoidance | Prefer the ReadAsync(Memory<byte>) / WriteAsync(ReadOnlyMemory<byte>) overloads to avoid array rentals. HookSmeagol forwards the exact Memory instance to the hook. | | Buffer reuse | If a hook needs a temporary buffer (e.g., for decryption), allocate it once in the hook’s constructor and reuse it across calls. | | Async‑over‑sync | Never call .Result or .Wait() inside a hook; it can dead‑lock the caller. Use await all the way. | | Seek support | Some inner streams are non‑seekable (e.g., network sockets). The hook must check inner.CanSeek before forwarding Seek . A typical pattern is to throw NotSupportedException if the underlying stream can’t seek. | | Cancellation | Pass the caller’s CancellationToken straight to inner async calls and to any async hook work. This keeps the whole pipeline responsive. | | Thread‑safety | HookSmeagol itself is not thread‑safe – it mirrors the underlying stream’s contract. If you need concurrent reads/writes, wrap the whole pipeline in a SemaphoreSlim or expose a thread‑safe façade. |
|
|
00:00 PLAYLIST (0) |