Skip to content

Anchors API ​

While the Owner API gives a scope a single identity, you often need to associate additional context objects — a database connection, a cache, an environment context. Anchors let you attach multiple named or typed objects to the scope and compose capabilities onto them.

Two kinds exist: typed anchors (keyed by type, one per type) and named anchors (keyed by string, for multiple instances of the same type).

Typed Anchors ​

Setting ​

csharp
var db = new DatabaseConnection("connstr");
scope.Anchors.Set<DatabaseConnection>(db);

Getting ​

csharp
// Get — returns null if not set or collected
var db = scope.Anchors.Get<DatabaseConnection>();

// GetOrThrow — throws if not set or collected
var db = scope.Anchors.GetOrThrow<DatabaseConnection>();

// TryGet — out-parameter pattern
if (scope.Anchors.TryGet<DatabaseConnection>(out var db))
{
    db.Query("SELECT 1");
}

Named Anchors ​

Setting ​

csharp
scope.Anchors.Set("primary-db", primaryDb);
scope.Anchors.Set("replica-db", replicaDb);

Getting ​

csharp
// Get — returns null if not set or collected
var db = scope.Anchors.Get("primary-db");

// GetOrThrow — throws if not set or collected
var db = scope.Anchors.GetOrThrow("primary-db");

// TryGet — out-parameter pattern
if (scope.Anchors.TryGet("primary-db", out var db))
{
    // use db
}

Composing via Anchors ​

Typed ​

csharp
scope.Anchors.Set<DatabaseConnection>(db);
scope.Anchors.ComposeFor<DatabaseConnection>()
    .Add(new PoolingCapability { MaxSize = 10 })
    .Build();

Named ​

csharp
scope.Anchors.Set("cache", cache);
scope.Anchors.Compose("cache")
    .Add(new ExpirationCapability { Ttl = TimeSpan.FromMinutes(5) })
    .Build();

Retrieving Compositions ​

Typed ​

csharp
Composition? comp = scope.Anchors.GetCompositionFor<DatabaseConnection>();
Composition required = scope.Anchors.GetRequiredCompositionFor<DatabaseConnection>();

if (scope.Anchors.TryGetCompositionFor<DatabaseConnection>(out var comp))
{
    // use composition
}

Named ​

csharp
Composition? comp = scope.Anchors.GetComposition("cache");
Composition required = scope.Anchors.GetRequiredComposition("cache");

if (scope.Anchors.TryGetComposition("cache", out var comp))
{
    // use composition
}

Retrieving Composers ​

Typed ​

csharp
Composer? c = scope.Anchors.GetComposerFor<DatabaseConnection>();
Composer required = scope.Anchors.GetRequiredComposerFor<DatabaseConnection>();

if (scope.Anchors.TryGetComposerFor<DatabaseConnection>(out var composer))
{
    // composer still in registry
}

Named ​

csharp
Composer? c = scope.Anchors.GetComposer("cache");
Composer required = scope.Anchors.GetRequiredComposer("cache");

if (scope.Anchors.TryGetComposer("cache", out var composer))
{
    // use composer
}

Fluent Chaining ​

Anchors methods return ScopeAnchorsApi:

csharp
scope.Anchors
    .Set<DatabaseConnection>(db)
    .Set("cache", cache)
    .Scope  // return to scope
    .Compose("something")
    .Build();

Weak References ​

Like the Owner API, anchors are stored as weak references. Anchored objects can be garbage collected without the scope preventing it.

Typed vs Named — When to Use ​

Use CaseTypedNamed
One instance per typeYes—
Multiple instances of same type—Yes
Compile-time type safetyYes—
Dynamic/runtime keys—Yes

Released under the Apache-2.0 License.