StageKit.Primitives 0.2.6

There is a newer version of this package available.
See the version list below for details.
dotnet add package StageKit.Primitives --version 0.2.6
                    
NuGet\Install-Package StageKit.Primitives -Version 0.2.6
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="StageKit.Primitives" Version="0.2.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="StageKit.Primitives" Version="0.2.6" />
                    
Directory.Packages.props
<PackageReference Include="StageKit.Primitives" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add StageKit.Primitives --version 0.2.6
                    
#r "nuget: StageKit.Primitives, 0.2.6"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package StageKit.Primitives@0.2.6
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=StageKit.Primitives&version=0.2.6
                    
Install as a Cake Addin
#tool nuget:?package=StageKit.Primitives&version=0.2.6
                    
Install as a Cake Tool

StageKit.Primitives

Logo

License GitHub repo size Code size Nuget GitHub Sponsors

StageKit.Primitives is a dependency-light .NET package with reusable low-level helpers used by StageKit libraries and available for other libraries or apps.

All public helpers are exposed from the StageKit.Primitives namespace. IO-related source files are grouped under an IO/ folder for organization only.

Features

  • Atomic file writes with temporary-file replacement through SafeFile
  • Stream-based atomic file writes through SafeFileStream
  • Path, temporary file, and temporary directory helpers
  • Disposable base type with thread-safe idempotent disposal through DisposableObject
  • Finalizable disposable base type through UnmanagedDisposableObject
  • Leave-open lifecycle base type through LeaveOpenDisposableObject
  • SafeHandle wrapper for pinned GCHandle scenarios through GCSafeHandle
  • MemoryManager<T> wrapper for externally owned unmanaged buffers through UnmanagedMemoryManager<T>

Install

dotnet add package StageKit.Primitives

Requirements

  • .NET 8 or newer
  • C# latest language version

SafeFile

Use SafeFile when you need to write a file through a temporary file and then replace the destination.

using StageKit.Primitives;

SafeFile.WriteAllText("settings.json", json);

SafeFile.Write("settings.json", stream =>
{
    JsonSerializer.Serialize(stream, settings);
});

Async writes are supported:

await SafeFile.WriteAllTextAsync(
    "settings.json",
    json,
    cancellationToken: cancellationToken);

Temporary files use this pattern:

<destination>.tmp.<guid>

Use SafeFile.IsTemporaryPathFor(...) when filtering a directory that may contain temporary files for an in-progress write:

if (SafeFile.IsTemporaryPathFor(candidatePath, destinationPath))
{
    return;
}

SafeFileStream

Use SafeFileStream when you want stream-style writes with atomic replacement.

using StageKit.Primitives;
using System.Text;

using var stream = new SafeFileStream("settings.json");
stream.Write(Encoding.UTF8.GetBytes(json));
// Dispose commits by default.

Set commitOnDispose to false when you want to commit explicitly:

await using var stream = new SafeFileStream("settings.json", commitOnDispose: false);
await stream.WriteAsync(buffer, cancellationToken);
await stream.CommitAsync(cancellationToken);

If a SafeFileStream is disposed without committing and commitOnDispose is false, the temporary file is deleted and the destination is left unchanged.

IO Helpers

Use PathUtilities for platform-aware path comparisons and archive entry normalization:

if (!PathUtilities.IsSubPathOf(candidatePath, rootPath))
{
    throw new InvalidOperationException("Path escapes the root directory.");
}

var entryName = PathUtilities.NormalizeArchiveEntryName(relativePath);

Use TemporaryDirectory when a temporary workspace should be removed automatically:

using var directory = new TemporaryDirectory(prefix: "stagekit");
var outputPath = Path.Combine(directory.DirectoryPath, "output.json");

Use TemporaryFile when a temporary file should be removed unless explicitly kept:

using var file = new TemporaryFile(extension: "json");
await File.WriteAllTextAsync(file.FilePath, json);

file.Keep();

DisposableObject

Use DisposableObject for classes that need idempotent deterministic cleanup.

using StageKit.Primitives;

public sealed class Worker : DisposableObject
{
    private readonly Stream _stream;

    public Worker(Stream stream)
    {
        _stream = stream;
    }

    public void Run()
    {
        ThrowIfDisposed();

        // Use the stream.
    }

    protected override void DisposeManaged()
    {
        _stream.Dispose();
    }
}

DisposeManaged() runs for normal Dispose() calls. During explicit disposal, DisposeUnmanaged() runs after managed cleanup is attempted, even if managed cleanup throws. The base class does not define a finalizer; types that directly own unmanaged resources should prefer SafeHandle or use UnmanagedDisposableObject.

UnmanagedDisposableObject is available when a type directly owns unmanaged resources and needs finalizer fallback. Prefer SafeHandle when the resource is a native handle.

LeaveOpenDisposableObject

Use LeaveOpenDisposableObject when a type needs to expose a leave-open option for a resource owned by the caller.

using StageKit.Primitives;

public sealed class StreamWriterOwner : LeaveOpenDisposableObject
{
    private readonly Stream _stream;

    public StreamWriterOwner(Stream stream, bool leaveOpen)
        : base(leaveOpen)
    {
        _stream = stream;
    }

    protected override void DisposeManaged()
    {
        if (!LeaveOpen)
        {
            _stream.Dispose();
        }
    }
}

Derived classes are responsible for honoring LeaveOpen.

GCSafeHandle

GCSafeHandle wraps a GCHandle in a SafeHandle so pinned memory can be released reliably.

using StageKit.Primitives;

var buffer = new byte[1024];
using var handle = new GCSafeHandle(buffer);

IntPtr address = handle.DangerousGetHandle();

Use this only when pinning is necessary, such as interop paths that require a stable address. Keep pinning lifetimes short.

UnmanagedMemoryManager

Use UnmanagedMemoryManager<T> when an externally owned unmanaged buffer needs to be exposed as Memory<T>.

using StageKit.Primitives;

using var manager = new UnmanagedMemoryManager<byte>(bufferAddress, bufferLength);
Memory<byte> memory = manager.Memory;

The manager does not allocate, pin, or free the underlying memory. The caller must keep the buffer alive and fixed for every Memory<T> or MemoryHandle produced by the manager.

License

StageKit.Primitives is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on StageKit.Primitives:

Package Downloads
StageKit

Lightweight .NET application infrastructure for JSON settings, autosave, schema migration, atomic persistence, backups, support bundles, retention, onboarding state, single-instance guards, crash reports, and unhandled exception handling.

EmguExtensions

A high-performance .NET library that extends Emgu.CV (OpenCV wrapper) with zero-copy Span/Memory Mat accessors, async stream copy helpers, ROI utilities, pluggable Mat compression (PNG, Deflate, GZip, ZLib, Brotli, Zstd), CMat for memory-efficient compressed image storage, structured contour hierarchy wrappers, and drawing helpers for polygons and multi-line text rendering.

StageKit.Updatum

Secure GitHub release discovery, download verification, and cross-platform application updates for .NET applications.

StageKit.Fallout

Reusable .NET build pipeline for self-contained publishing, runtime manifests, portable archives, installers, macOS bundles, and Linux distribution packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.4.0 333 9/14/2026
0.3.8 159 9/11/2026
0.3.7 138 9/11/2026
0.3.6 169 9/10/2026
0.3.5 145 9/10/2026
0.3.4 150 9/9/2026
0.3.3 147 9/8/2026
0.3.2 164 9/5/2026
0.3.1 145 9/5/2026
0.3.0 146 9/3/2026
0.2.6 124 8/25/2026
0.2.5 126 8/24/2026
0.2.4 769 7/20/2026
0.2.3 153 7/19/2026
0.2.2 541 6/22/2026
0.2.1 158 6/7/2026
0.2.0 243 5/27/2026