Support IConfiguration/Options for NServiceBus configuration #319
Description
The generic host has built-in support for the .NET Configuration features. This allows configuration values to be retrieved and from various sources and by bound to typed configuration classes via the Options pattern.
NServiceBus has it's completely separate configuration API though which is focused around a code-first user experience. This is extremely powerful and flexible but requires additional effort when trying configure NServiceBus from settings retrieves via environment variables, settings files, process parameters and more, e.g. to change the immediate retry setting based on a configuration value, the mapping needs to be done manually:
builder.UseNServiceBus(ctx =>
{
// ...
endpointConfiguration.Recoverability().Immediate(c =>
c.NumberOfRetries(ctx.Configuration.GetValue<int>("immediate-retries")));
// ...
});
Instead, when providing a suitable options type, the settings can be bound like this:
NServiceBusOptions options = ctx.Configuration.Get<NServiceBusOptions>();
This way, supported settings can be directly configured in a valid configuration source.
It is also possible to continue to configure options directly in code, e.g. like this:
builder.ConfigureServices((context, collection) =>
{
collection.AddOptions<NServiceBusOptions>().Configure(options =>
{
options.ImmediateRetries = 10;
});
});
but these options are then only available via DI which is typically too late for the endpoint configuration.
Besides the missing support for an NServiceBus options type, this becomes trickier when taking into account the downstream package's configuration. E.g. transports, persisters, serializer, and other packages provide their own configuration extension methods.
Note that the transport configuration in v8 can already support IConfiguration for many settings since the TransportDefinition
classes have been reshaped into simpler classes with properties rather than extension methods. This allows to bind most of the transport configuration settings directly from the IConfiguration
. This even works with transports that contain mandatory ctor arguments (like connection strings) since the binding approach is able to use private and internal actors and properties (which currently exist because of backward compatibility). Some more complicated configuration options that use delegates can't be configured via simple configuration settings however.