Lesson 5.1: Author a .NET protocol plugin
Difficulty: Intermediate | Duration: 18 min | Prerequisites: Unit 0; .NET 10 SDK
Runnable scaffold. This lesson ships
start/(a plugin that compiles + is discovered but surfaces no services — twoTODOs) andcompleted/(the workingPirate Speakprotocol with a unaryTranslatemethod).cd start, fill the TODOs, then diff againstcompleted/. Both build against the publishedKuestenlogik.Bowire2.1.0 package. This hand-writtenIBowireProtocolis the same shapedotnet new bowire-pluginemits — minus the test project + CI the template adds.
Overview
Build a protocol plugin, pack it as a NuGet, install it, and watch a fresh workbench discover it on startup. The contract is small: implement IBowireProtocol, ship the assembly, and Bowire's plugin pipeline does the rest.
Steps
1. Scaffold from the template
dotnet new install Kuestenlogik.Bowire.Templates
dotnet new bowire-plugin \
-n Bowire.Plugin.Pirate --ProtocolId pirate \
--DisplayName "Pirate Speak" --PluginClassName PirateProtocol --Author "You"
cd Bowire.Plugin.Pirate
dotnet build
The scaffold emits a .slnx with the plugin assembly (an IBowireProtocol stub), an xUnit test project asserting the discovered shape, pinned Directory.Packages.props, and a CI workflow.
2. Implement IBowireProtocol
The interface is the whole surface: advertise a service + methods (so discovery can render them), and handle invocation:
- Discovery — return the services/methods the workbench shows in the sidebar.
InvokeAsync— unary call: take the request, return the response.InvokeStreamAsync— server-streaming (yield frames); return an empty stream for unary-only protocols.OpenChannelAsync— bidirectional; returnnullwhen unsupported.
Swap the stub's body for real wire work — HttpClient.SendAsync, MQTTnet.PublishAsync, GrpcChannel.ForAddress, or anything else.
Study a real one.
Bowire.Protocol.AkkaimplementsIBowireProtocolwith a single server-streaming method (Tap/MonitorMessages) that yieldsTappedMessageenvelopes from an Akka.NET mailbox tap — a genuine, shipped plugin withsrc/,tests/andsamples/you can read end to end.
3. Pack + install (CLI shape)
dotnet pack -c Release -o nupkgs
bowire plugin install Bowire.Plugin.Pirate --source ./nupkgs
bowire plugin list
bowire plugin also covers download (offline nupkgs), uninstall, update, and inspect. Restart the workbench — your protocol appears in the sidebar.
4. Or reference it in an embedded host
In an embedded host (Unit 4), a plain <PackageReference Include="Bowire.Plugin.Pirate" /> is enough — AddBowire() discovers registered IBowireProtocol implementations through DI. Same NuGet, two install paths.
Key Takeaways
IBowireProtocolis the contract — discovery +InvokeAsync/InvokeStreamAsync/OpenChannelAsync.dotnet new bowire-pluginscaffolds everything;dotnet pack→bowire plugin install(CLI) orPackageReference(embedded).Bowire.Protocol.Akkais a real, complete example to learn from.
What's Next
Continue: → Lesson 5.2: Polyglot sidecar plugin