Inter-addon services

Coordinate addons through declared dependencies, typed versioned services and local JSON events.

Declare dependencies first

A runtime service lookup does not replace manifest metadata. Use DependsOn when the consumer cannot run without the provider, and OptionalDependsOn when it has a fallback. This gives deterministic activation order before either addon publishes a service.

Typed services

A service key is <owner addon id>:<name>. Registration records the exact contract type and a valid version. Consumers can read the version directly or require a SemVer constraint. Both sides must use the same contract type.

1// Publisher
2context.RegisterService<IMarketPrices>( "prices", service, version: "2.1.0" );
3context.PublishAddonEvent( "catalog.changed", new { revision = 12 } );
4
5// Consumer. Declare the publisher in DependsOn or OptionalDependsOn too.
6if ( context.TryGetService<IMarketPrices>(
7 ownerAddonId: "market",
8 name: "prices",
9 versionConstraint: "^2.0.0",
10 out var prices,
11 out var resolvedVersion ) )
12{
13 UsePrices( prices!, resolvedVersion );
14}
15
16context.SubscribeAddonEvent(
17 publisherAddonId: "market",
18 topic: "catalog.changed",
19 handler: payload => RefreshCatalog( payload ),
20 priority: 50 );

Local event bus

Topics are owned by the publisher id, JSON serialized and delivered in-process. Higher priorities run first, then subscriber id and registration order. Three consecutive recoverable failures quarantine one subscription for the activation.

Limits and teardown

  • 32 services per addon.
  • 128 local event subscriptions per addon.
  • Names and topics are at most 64 characters with lowercase letters, digits, dot, underscore and hyphen.
  • Local event payloads are capped at 65,536 UTF-8 bytes.
  • Teardown removes services owned by the addon and subscriptions where it is publisher or subscriber.