NCode.PropertyBag 1.2.0

Prefix Reserved
dotnet add package NCode.PropertyBag --version 1.2.0
                    
NuGet\Install-Package NCode.PropertyBag -Version 1.2.0
                    
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="NCode.PropertyBag" Version="1.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="NCode.PropertyBag" Version="1.2.0" />
                    
Directory.Packages.props
<PackageReference Include="NCode.PropertyBag" />
                    
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 NCode.PropertyBag --version 1.2.0
                    
#r "nuget: NCode.PropertyBag, 1.2.0"
                    
#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 NCode.PropertyBag@1.2.0
                    
#: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=NCode.PropertyBag&version=1.2.0
                    
Install as a Cake Addin
#tool nuget:?package=NCode.PropertyBag&version=1.2.0
                    
Install as a Cake Tool

ci Nuget

NCode.PropertyBag

A lightweight, strongly-typed property bag library for .NET that provides type-safe key-value storage with support for scoped values, cloning, and dependency injection.

Features

  • Strongly-Typed Keys - Type-safe PropertyBagKey<T> ensures compile-time type checking when storing and retrieving values
  • Nullable Value Support - Explicitly store and retrieve null values for reference types and nullable value types
  • Read-Only Interface - IReadOnlyPropertyBag for passing property bags to code that should only read values
  • Fluent API - Method chaining support for Set and Remove operations
  • Scoped Values - Temporarily override values with automatic cleanup using IPropertyBagScope
  • Cloning Support - Create independent copies with Clone(), supporting deep cloning for ICloneable values
  • Lazy Initialization - Empty property bags are lightweight with no memory allocated until first use
  • Dictionary Access - DefaultPropertyBag implements IReadOnlyDictionary<PropertyBagKey, object?> for enumeration
  • Dependency Injection - Built-in integration with Microsoft.Extensions.DependencyInjection
  • Convenience Extensions - Automatic key name inference using CallerArgumentExpression

Installation

dotnet add package NCode.PropertyBag

Or for abstractions only:

dotnet add package NCode.PropertyBag.Abstractions

Quick Start

Basic Usage

// Define keys (typically as static readonly fields)
public static readonly PropertyBagKey<string> UserNameKey = new("UserName");
public static readonly PropertyBagKey<int> UserAgeKey = new("UserAge");

// Create and use a property bag
var propertyBag = PropertyBagFactory.Create();

propertyBag
    .Set(UserNameKey, "Alice")
    .Set(UserAgeKey, 30);

if (propertyBag.TryGetValue(UserNameKey, out var userName))
{
    Console.WriteLine($"User: {userName}"); // Output: User: Alice
}

Scoped Values

Temporarily override a value that automatically restores when disposed:

var cultureKey = new PropertyBagKey<string>("Culture");
propertyBag.Set(cultureKey, "en-US");

using (propertyBag.Scope(cultureKey, "fr-FR"))
{
    // Within this scope, Culture is "fr-FR"
    propertyBag.TryGetValue(cultureKey, out var culture); // "fr-FR"
}

// After disposal, Culture is restored to "en-US"
propertyBag.TryGetValue(cultureKey, out var restored); // "en-US"

Dependency Injection

Register services with the DI container:

services.AddPropertyBag();

Then inject IPropertyBagFactory where needed:

public class MyService
{
    private readonly IPropertyBagFactory _factory;

    public MyService(IPropertyBagFactory factory)
    {
        _factory = factory;
    }

    public IPropertyBag CreateContext() => _factory.Create();
}

Convenience Extensions

Use automatic key name inference:

var connectionString = "Server=localhost;Database=test";
var timeout = TimeSpan.FromSeconds(30);

// Keys are inferred as "connectionString" and "timeout"
propertyBag
    .Set(connectionString)
    .Set(timeout);

// Retrieve with inferred key name
// Note: declare variable first - inline declaration (out string? x) won't infer the key name correctly
string? connectionString;
if (propertyBag.TryGet(out connectionString)) // Key inferred as "connectionString"
{
    Console.WriteLine(connectionString);
}

Nullable Values

Null values can be explicitly stored and retrieved:

var optionalNameKey = new PropertyBagKey<string?>("OptionalName");

// Explicitly store null
propertyBag.Set(optionalNameKey, null);

// TryGetValue returns true because the key exists (even though value is null)
if (propertyBag.TryGetValue(optionalNameKey, out var name))
{
    // name is null here, but the key was found
    Console.WriteLine(name ?? "(not set)");
}

// This is different from a missing key
var missingKey = new PropertyBagKey<string?>("Missing");
if (!propertyBag.TryGetValue(missingKey, out _))
{
    // Key does not exist
}

API Overview

Abstractions (NCode.PropertyBag.Abstractions)

Type Description
PropertyBagKey Non-generic key with Type and Name properties
PropertyBagKey<T> Strongly-typed key for type-safe value access
IReadOnlyPropertyBag Read-only interface with TryGetValue and Clone
IPropertyBag Mutable interface adding Set, Remove, and Scope
IPropertyBagScope Disposable scope for temporary value overrides
IPropertyBagFactory Factory interface for creating property bags
PropertyBagExtensions Convenience methods with automatic key inference

Implementation (NCode.PropertyBag)

Type Description
DefaultPropertyBag Dictionary-based implementation with lazy initialization
DefaultPropertyBagFactory Default factory with singleton support
DefaultPropertyBagScope Scope implementation that removes values on dispose
PropertyBagFactory Static convenience class for creating property bags
DefaultRegistration DI registration extension methods

License

Licensed under the Apache License, Version 2.0. See LICENSE.txt for details.

Target Frameworks

  • .NET 8.0
  • .NET 10.0

Release Notes

  • v1.0.0 - Initial release
  • v1.0.1 - Fix CI build
  • v1.1.0 - Added NET 8.0 build
  • v1.1.1 - Fixed TryGet documentation example to show correct variable declaration pattern
  • v1.2.0 - Added explicit support for nullable values; TryGetValue now returns true when a key exists with a null value
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.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.0 84 1/19/2026
1.1.1 83 1/19/2026
1.1.0 84 1/19/2026
1.0.1 84 1/19/2026
1.0.0 84 1/19/2026

Built on 2026-01-19 18:51:53Z