Capability Composition for .NET — extensible, type-safe, and high-performance.
$ dotnet add package Cocoar.Capabilities
A high-performance, low-allocation capability composition library for .NET that implements the Capability Composition pattern for building extensible, type-safe systems.
dotnet add package Cocoar.Capabilitiesusing Cocoar.Capabilities;
// Create a scope to manage capabilities
using var scope = new CapabilityScope();
// Define your subject
var document = new Document("README.md");
// Compose capabilities
var composition = scope.Compose(document)
.Add(new EditCapability())
.Add(new PrintCapability())
.Add(new ShareCapability())
.Build();
// Retrieve and use capabilities
var capabilities = composition.GetAll<EditCapability>();
foreach (var cap in capabilities)
{
cap.Edit(document);
}Enforce a single "primary" capability per subject:
public record UserPrimaryCapability(string UserId, string Name) : IPrimaryCapability;
var composition = scope.Compose(user)
.Add(new UserPrimaryCapability("user123", "John Doe"))
.Add(new AdminCapability("Level2"))
.Build();
// Retrieve the primary capability
var primary = composition.GetPrimary();
Console.WriteLine($"User: {primary.Name}");Register a single capability under multiple contract types:
var composition = scope.Compose(myObject)
.AddAs<(IValidator, IFormatter)>(new DataProcessor())
.Build();
// Access via either contract
var validator = composition.GetFirstOrDefault<IValidator>();
var formatter = composition.GetFirstOrDefault<IFormatter>();Associate scopes with well-known subjects for enhanced composability:
// Setup scope with owner and anchors
var pipeline = new PipelineHost("Main");
var envContext = new EnvironmentContext { Name = "Production" };
using var scope = new CapabilityScope();
scope.Owner.Set(pipeline).Scope
.Anchors.Set<EnvironmentContext>(envContext).Scope
.Anchors.Set("tenant", tenantContext);
// Later, compose capabilities using owner/anchors
scope.Owner.Compose<PipelineHost>()
.Add(new DiagnosticsCapability())
.Build();
scope.Anchors.Compose<EnvironmentContext>()
.Add(new EnvironmentCapability())
.Build();
// Retrieve owner or anchors (throwing)
var owner = scope.Owner.Get<PipelineHost>();
var env = scope.Anchors.Get<EnvironmentContext>();
// Safe retrieval for long-running scopes
if (scope.Owner.TryGet<PipelineHost>(out var pipelineOwner))
{
// Owner is alive, use it
}
if (scope.Anchors.TryGet<EnvironmentContext>(out var envAnchor))
{
// Anchor is alive, use it
}Learn more: Owner and Anchor Quick Reference
IPrimaryCapability)This project is licensed under the Apache License, Version 2.0. See NOTICE for attribution.
"Cocoar" and related marks are trademarks of COCOAR e.U. Use of the name in forks or derivatives should preserve attribution and avoid implying official endorsement. See TRADEMARKS for permitted and restricted uses.