MyServiceBusDocs

Experimental · .NET 11 Preview

Experimental union-shaped contracts in .NET 11.

MyServiceBus's experimental .NET 11 support lets C# and Raven applications use standard union semantics for multi-message consumers and request responses. C# remains the primary .NET API; Raven shows how the same runtime contract can become especially concise when the language understands unions directly.

Available in the core NuGet packages

Sundstrom.MyServiceBus and Sundstrom.MyServiceBus.Abstractions include both net10.0 and experimental net11.0 assets. Use a .NET 11 preview SDK and target net11.0 to activate this API. Preview runtime and language behavior may still change before .NET 11 is stable.

Keep the message contracts ordinary

Union support does not create a new wire-level message. Define concrete contracts as usual; the union is a local way to describe which of them a consumer or response can contain.

C#
Loading code…

Handle several message types with a custom C# union

The custom OrderCommand union expands into one topology registration for each case. A sent SubmitOrder is still identified and serialized as SubmitOrder; MyServiceBus constructs the union carrier only when invoking the consumer method.

C#
Loading code…

This is an alternative to separate consumer methods or an inheritance hierarchy. Those existing styles remain supported and may be clearer when the cases do not belong together.

Model request outcomes as variants

Response<T1, T2> implements the .NET union ABI and has a constructor for each response case. That enables implicit case conversion, exhaustive pattern matching, and non-boxing TryGetValue access while retaining the MyServiceBus response API.

C#
Loading code…

Raven makes the same model feel native

Raven is a preview .NET programming language that compiles to CLR assemblies and is designed to express modern .NET features with concise syntax. It can reference the same NuGet packages, types, and runtime contracts as a C# application. Raven's syntax and behavior may change while it remains in preview.

Raven writes System.Union<SubmitOrder, CancelOrder> as SubmitOrder | CancelOrder. MyServiceBus recognizes the shared union ABI, so no Raven-specific adapter or base message type is required. This is where the .NET 11 work particularly complements Raven: the bus provides topology and dispatch semantics while the language provides concise variants and matching.

Raven also supports top-level (namespace-level) functions. A consumer method can therefore be an attributed function directly, as in the example below, without introducing a static container class solely to host the handler.

Raven
Loading code…

Preserve cross-language exchange

The union carrier never becomes the interoperable contract. Java and other clients continue to publish and consume SubmitOrder and CancelOrder independently. They do not need union syntax, the .NET ABI, or knowledge that a C# or Raven endpoint groups those messages in one handler.

Java
Loading code…

Understand today's experimental boundary

  • Reflection discovery recognizes the standard union ABI through a cached descriptor and constructor delegates.
  • The C# source generator expands named-union inputs into direct per-case adapters. CI executes both cases in a .NET 11 Runtime Async NativeAOT application and verifies that topology contains only the concrete contracts.
  • Raven source is not visible to the C# generator, so Raven union consumers still use reflection unless a future Raven-owned manifest supplies generated registrations.
  • Broker-backed union delivery and union-valued handler responses remain future verification slices.
  • A typed ConsumeContext<TUnion> parameter is not supported yet; consume the union value directly.
  • JSON writes the active case shape. Reading an object-shaped union requires an explicit classifier or discriminator policy.
  • The concrete case types—not the union carrier—control topology names and wire compatibility.

For the broader language story, including the experimental saga! macro, see Raven and MyServiceBus. For the current registration model, see consumer methods. For the generated native path and its remaining application-level constraints, see AOT compilation.