A thread safe, async safe context management system with built-in security boundaries for .NET applications.
- 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)
usingModularityKit.Context.Abstractions;usingModularityKit.Context.Extensions;// 1. Define your contextpublicclassMyContext:IContext{publicstringId{get;}publicDateTimeOffsetCreatedAt{get;}publicstringUserId{get;}publicstringTenantId{get;}}// 2. Register in DIservices.AddContext<MyContext>();// 3. Use in your codepublicclassOrderService(IContextAccessor<MyContext>context){publicvoidProcessOrder(){varctx=context.RequireCurrent();Console.WriteLine($"Processing for user: {ctx.UserId}");}}// 4. Execute with contextvarcontext=newMyContext("ctx-1","user-123","tenant-456");awaitcontextManager.ExecuteInContext(context,async()=>{orderService.ProcessOrder();});publicclassOrderService{// Passing context everywhere - painful!publicasyncTaskCreateOrder(stringuserId,stringtenantId,stringcorrelationId){awaitValidateOrder(userId,tenantId,correlationId);awaitProcessPayment(userId,tenantId,correlationId);awaitSendEmail(userId,tenantId,correlationId);}}publicclassOrderService(IContextAccessor<MyContext>context){// Clean API - context flows automaticallypublicasyncTaskCreateOrder(){awaitValidateOrder();// Context flows automaticallyawaitProcessPayment();awaitSendEmail();}}- Installation & Setup - Complete setup guide
- Basic Usage - Learn the fundamentals
- Core Concepts - Understanding the architecture
- Multi-Tenant Applications - Building SaaS applications
- API Reference - Complete API documentation
- Best Practices - Tips and recommendations
publicclassDocumentService(IContextAccessor<MyContext>context){publicasyncTaskGetDocument(stringdocumentId){varctx=context.RequireCurrent();// Automatic tenant filteringreturnawait_db.Documents.Where(d =>d.TenantId==ctx.TenantId).Where(d =>d.Id==documentId).FirstOrDefaultAsync();}}Automatic tenant isolation using
IContextAccessorensures security and data separation.
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 →
- Create context per operation (request/job)
- Use
RequireCurrent()when context is expected - Let
ExecuteInContexthandle cleanup - Treat contexts as immutable
- Share context across operations
- Mutate context properties
- Use
Currentwithout null check - Store context in static fields
Read full best practices guide →
- IContext - Base context interface
- IContextAccessor<TContext> - Access current context
- IContextManager<TContext> - Manage context lifecycle
- AddContext<TContext>() - Register context infrastructure
- AddReadOnlyContextAccessor<TContext>() - Register read-only accessor
Built with ❤️ for .NET developers