Waystone.Monads.Extensions.DependencyInjection 7.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Waystone.Monads.Extensions.DependencyInjection --version 7.2.0
                    
NuGet\Install-Package Waystone.Monads.Extensions.DependencyInjection -Version 7.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Waystone.Monads.Extensions.DependencyInjection" Version="7.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Waystone.Monads.Extensions.DependencyInjection" Version="7.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Waystone.Monads.Extensions.DependencyInjection" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Waystone.Monads.Extensions.DependencyInjection --version 7.2.0
                    
#r "nuget: Waystone.Monads.Extensions.DependencyInjection, 7.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Waystone.Monads.Extensions.DependencyInjection@7.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Waystone.Monads.Extensions.DependencyInjection&version=7.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Waystone.Monads.Extensions.DependencyInjection&version=7.2.0
                    
Install as a Cake Tool

Waystone.Monads.Extensions.DependencyInjection

Authors the ambient Waystone.Monads configuration from a dependency injection container.

MonadOptions is ambient by design — Option and Result read it statically, so nothing is threaded through call sites and no monad gains a constructor dependency. What this package changes is only how those options are written: by the container at start-up rather than by a hand-written static call.

Install and configure

dotnet add package Waystone.Monads.Extensions.DependencyInjection
builder.Services.AddWaystoneMonads(
    options => options.UseFallbackErrorCode("Contoso"));

var app = builder.Build();

app.Services.UseWaystoneMonads();

Everything this package ships is in the Microsoft.Extensions.DependencyInjection namespace, which a host application already has in scope — no extra using, including for ReadFromConfiguration.

AddWaystoneMonads returns a MonadServicesBuilder rather than the collection. Its Services property is the same collection you passed in, so carry on from there:

builder.Services.AddWaystoneMonads()
       .Services.AddSingleton<IClock, SystemClock>();

The builder exists so a companion package can offer a call that only makes sense once registration has happened — Waystone.Monads.Extensions.Hosting hangs EnableInstallOnStart() off it, so there is no way to ask for the install without first asking for the registration.

Calling AddWaystoneMonads more than once accumulates rather than conflicts. Each configure delegate is kept and they run in registration order at install time, so a later call overrides an earlier one. Everything else it does is idempotent, which makes it safe for a library to call during its own registration without knowing whether the application already has.

Two calls, and why

AddWaystoneMonads registers. UseWaystoneMonads installs. They are separate because the configuration needs services the container has not built yet — an ILoggerFactory does not exist while the collection is still being populated.

This is Serilog's bootstrap-logger split, with the expensive half left out. Serilog buffers events written before the bind, because a log event emitted early is lost forever. Nothing is lost here: options read between the two calls are answered from the defaults, which are valid settings rather than a broken state.

Forgetting the second call is the failure mode, and it is silent — the library keeps working on defaults. So it is instrumented instead. A read taken after AddWaystoneMonads and before UseWaystoneMonads writes a Waystone.Monads.ConfigurationNotApplied event to the Waystone.Monads DiagnosticListener:

// In a test suite, subscribe and throw to make the omission fatal.
listener.Subscribe(observer, name => name == "Waystone.Monads.ConfigurationNotApplied");

The signal is held rather than spent while nothing is subscribed, so a subscriber attached at any point before the install still receives it.

Waystone.Monads.Extensions.Hosting removes the second call on a host by running it from the host's own start-up sequence.

What the container supplies

At install time, three things are applied in order, each overwriting the last:

  1. The options already in effect, so an earlier MonadOptions.Configure call is carried forward rather than discarded.
  2. ErrorCodeFactory, if the container holds one.
  3. Every delegate passed to AddWaystoneMonads, in registration order.

So a delegate has the last word.

ErrorCodeFactory is the only thing resolved for you. Everything else a companion package needs is wired by a delegate you pass. Take the overload that hands you the built provider:

builder.Services.AddWaystoneMonads((provider, options) =>
    options.UseFallbackErrorCode("Contoso")
           .UseLoggerFactoryFrom(provider));

UseLoggerFactoryFrom ships from Waystone.Monads.Extensions.Logging, so the package you installed is the one you call. Installing this package does not drag that one in, and installing that one does not silently change what this one does.

Resolve singletons only. The options are one process-wide snapshot, so a scoped service captured here outlives the scope it came from.

ErrorCodeFactory has no interface. It is a public non-sealed class with virtual members, so you override it by subclassing:

builder.Services.AddSingleton<ErrorCodeFactory, ContosoErrorCodeFactory>();

Registered before AddWaystoneMonads or after, it wins either way: the default is registered with TryAddSingleton.

A scoped service cannot be held here. The options are one process-wide snapshot published once, so anything resolved into them outlives the scope it came from. Register an ErrorCodeFactory as scoped and, depending on whether the container validates scopes, the install either fails or quietly captures the root instance and hands it to every request for the life of the process. Per-request configuration is a separate problem and is not solved by this package.

Reading from configuration

Configuration binding is opt-in, mirroring Serilog's ReadFrom.Configuration(). AddWaystoneMonads never reaches for an IConfiguration on its own:

builder.Services.AddWaystoneMonads(
    options => options.ReadFromConfiguration(builder.Configuration));
{
  "WaystoneMonads": {
    "FallbackErrorCode": "Contoso",
    "FallbackErrorMessage": "Something went wrong.",
    "CatchesCancellation": false
  }
}

Every key is optional, and an absent one leaves its setting alone — a section with one key changes one setting. Pass a second argument to read a section other than WaystoneMonads.

A key that is present but unusable throws, which is the point of opting in: an empty FallbackErrorCode, or a CatchesCancellation that is not true or false, stops start-up where the mistake is written rather than degrading to a default nobody chose.

"CatchesCancellation" is honoured either way round, so false puts the setting back even where code earlier in the chain called UseCancellationAsFailure().

Binding goes through the builder's Use* methods rather than the reflection binder, because the settings have no public setters to bind to.

Without a Microsoft container

Both services are resolved through IServiceProvider.GetService itself rather than through any container-specific API, so UseWaystoneMonads works on a provider produced by any conforming container. AddWaystoneMonads needs an IServiceCollection; a container that populates itself from one — which most do — is enough.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Waystone.Monads.Extensions.DependencyInjection:

Package Downloads
Waystone.Monads.Extensions.Hosting

Installs the container-registered Waystone.Monads configuration from the host's own start-up sequence, so an application cannot forget to.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
7.3.0 36 9/13/2026
7.2.0 83 9/9/2026
7.1.0 134 9/4/2026
7.1.0-beta.2 58 9/3/2026
7.1.0-beta.1 65 9/2/2026
7.0.1 125 8/30/2026
7.0.0 118 8/30/2026
7.0.0-beta.3 66 8/29/2026