Skip to content

ModularityKit/ModularityKit.Context

Repository files navigation

Context System

License .NET

A thread safe, async safe context management system with built-in security boundaries for .NET applications.

Features

  • Thread-Safe & Async-Safe - Built on AsyncLocal<T> for automatic context isolation
  • Security Boundaries - Defensive copy pattern prevents untrusted code from accessing sensitive data
  • Multi-Tenant Ready - Perfect for SaaS applications requiring tenant isolation
  • Plugin-Friendly - Safe context exposure to third-party plugins
  • Distributed Tracing - Built-in support for correlation IDs and trace context
  • High Performance - Minimal overhead (~100ns per operation)

Quick Start

using ModularityKit.Context.Abstractions;
using ModularityKit.Context.AspNet;

// 1. Define your context
public class MyContext : IContext
{
    public string Id { get; }
    public DateTimeOffset CreatedAt { get; }
    public string UserId { get; }
    public string TenantId { get; }
}

// 2. Register in DI
services.AddContext();

// 3. Use in your code
public class OrderService(IContextAccessor<MyContext> context)
{
    public void ProcessOrder()
    {
        var ctx = context.RequireCurrent();
        Console.WriteLine($"Processing for user: {ctx.UserId}");
    }
}

// 4. Execute with context
var context = new MyContext("ctx-1", "user-123", "tenant-456");

await contextManager.ExecuteInContext(context, async () =>
{
    orderService.ProcessOrder();
});

🎯 Why Use Context System?

Without Context System ❌

public class OrderService
{
    // Passing context everywhere - painful!
    public async Task CreateOrder(string userId, string tenantId, string correlationId)
    {
        await ValidateOrder(userId, tenantId, correlationId);
        await ProcessPayment(userId, tenantId, correlationId);
        await SendEmail(userId, tenantId, correlationId);
    }
}

With Context System ✅

public class OrderService(IContextAccessor<MyContext> context)
{
    // Clean API - context flows automatically
    public async Task CreateOrder()
    {
        await ValidateOrder();   // Context flows automatically
        await ProcessPayment();
        await SendEmail();
    }
}

Documentation

Getting Started

Guides

Reference


Multi Tenant SaaS

public class DocumentService(IContextAccessor<MyContext> context)
{
    public async Task GetDocument(string documentId)
    {
        var ctx = context.RequireCurrent();
        
        // Automatic tenant filtering
        return await _db.Documents
            .Where(d => d.TenantId == ctx.TenantId)
            .Where(d => d.Id == documentId)
            .FirstOrDefaultAsync();
    }
}

Automatic tenant isolation using IContextAccessor ensures security and data separation.

See full example →


Architecture

    Application Layer
        ├─ Trusted Code (Full Access)-> IContextAccessor<MyContext>
        └─ Untrusted Code (Read-Only) -> IContextAccessor<IReadOnlyContext>
                │
                ▼
    Context Infrastructure
        ├─ ContextStore (AsyncLocal)
        ├─ ContextAccessor
        └─ ContextManager
                │
                ▼
    Security Boundary
        └─ ReadOnlyContextSnapshot (Defensive Copy)

Learn more about architecture →


Best Practices

DO ✅

  • Create context per operation (request/job)
  • Use RequireCurrent() when context is expected
  • Let ExecuteInContext handle cleanup
  • Treat contexts as immutable

DON'T ❌

  • Share context across operations
  • Mutate context properties
  • Use Current without null check
  • Store context in static fields

Read full best practices guide →


API Reference

Core Interfaces

Extension Methods

View complete API reference →


Built with ❤️ for .NET developers

About

Lightweight context framework for modular applications.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages