Skip to content

Leader-election options with init-only properties can't be set via the AddXxxLeaderElection(options => ...) DI callback #145

Description

@steingran

Summary

Several leader-election options properties are declared init-only. The DI registration extensions configure options through an Action<TOptions> callback (services.Configure(configureOptions)), which receives an already-constructed instance. Assigning to an init-only property outside an object initializer is a compile error, so these properties cannot be set through the documented options => { ... } configuration pattern — the code simply won't build for consumers who try.

This was found while documenting the v2.0.0 Consul SessionLockDelay breaking change (PR #144): the README example originally used options.SessionLockDelay = ..., which doesn't compile for exactly this reason.

Affected properties

Provider File init-only properties
Consul ConsulLeaderElectionOptions.cs Datacenter, KeyPrefix, SessionTtl, SessionLockDelay
PostgreSQL PostgreSQLLeaderElectionOptions.cs AutoCreateTable, CommandTimeoutSeconds
Azure Blob Storage AzureBlobStorageLeaderElectionOptions.cs AutoCreateContainer, LeaseDuration

Note: the semaphore options classes (ConsulSemaphoreOptions, etc.) already use set and are not affected — this is limited to the older leader-election options.

Reproduction

builder.Services.AddConsulLeaderElection(options =>
{
    options.SessionLockDelay = TimeSpan.FromSeconds(10); // CS8852: init-only property cannot be assigned here
});

Current workarounds

  • Configuration binding works, because the binder sets properties via reflection (which can invoke init accessors):
    builder.Services.Configure<ConsulLeaderElectionOptions>(
        builder.Configuration.GetSection("Consul"));
  • Constructing the options directly via an object initializer (outside the Action<T> overload).

Suggested fix

Change these init accessors to set so they behave consistently with the rest of each options class (which already mixes set properties like Address and Token) and with the semaphore options. This makes the Action<TOptions> configure callback — the pattern shown throughout the README — actually usable for every property.

Since changing initset only widens what's allowed, it is source- and binary-compatible for existing consumers; a good candidate to fold into the v2.0.0 release. If instead the immutability is intentional, the DI extensions and README should be updated to steer users to configuration binding / object-initializer construction for these properties.

Filed from the PR #144 review discussion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions