Skip to content

Fix DI-activated projection evolver + multi-identity dispatcher (2.14.1)#470

Merged
jeremydmiller merged 1 commit into
mainfrom
fix-evolver-ctor-4185
Jun 24, 2026
Merged

Fix DI-activated projection evolver + multi-identity dispatcher (2.14.1)#470
jeremydmiller merged 1 commit into
mainfrom
fix-evolver-ctor-4185

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Two event-sourcing codegen regressions that surface when Marten/Polecat adopt the 2.14.x line (Marten master deliberately pinned the older generator to avoid them). Found while publishing the document-diagnostics stack (#469).

1. Generator — DI-activated projection (CS7036)

A projection registered via AddProjectionWithServices has only a constructor with injected dependencies (no parameterless ctor). The AggregateEvolver generator created the evolver's private shadow projection instance with new T(), which fails to compile (CS7036) — e.g. Marten's #4185 OrderProjection4185 : SingleStreamProjection with an IDocumentStore ctor param. When there is no public parameterless ctor, the shadow instance is now created without running the constructor (RuntimeHelpers.GetUninitializedObject), mirroring the aggregate no-parameterless-ctor fallback. The shadow instance only invokes the projection's stateless Create/Apply event methods.

2. Runtime — multi-identity dispatcher (#297)

When one aggregate is registered against multiple identity types (e.g. AggregateStream<CountOfLetters> with both Guid and string ids), the generator emits one self-aggregating evolver per TId, all keyed on the aggregate type with a null ProjectionType. tryUseAssemblyRegisteredEvolver selected the fallback by aggregate type alone and could pick the wrong-TId evolver, whose strongly-typed IGenerated*<TDoc,TId> interface checks then all failed — leaving _evolve unwired and tripping the "no source-generated dispatcher" backstop. The fallback now only accepts an evolver implementing a <TDoc, TId> contract for the current identity type.

Validation

  • New generator regression test (di_activated_projection_without_parameterless_ctor_compiles); generator suite 24/24.
  • Marten Bug_4185 (generator) + live_aggregation_with_string_identifiers (runtime) both pass; full Marten EventSourcingTests 1378/0/7 green against 2.14.1.

🤖 Generated with Claude Code

…lver + multi-identity dispatcher

Two regressions surfaced when Marten/Polecat adopt the 2.14.x event-sourcing codegen
(Marten master deliberately pinned the older generator to avoid them):

1. Generator (#4185): a projection registered via AddProjectionWithServices has only a
   constructor with injected dependencies (no parameterless ctor). The AggregateEvolver
   generator created the evolver's private shadow projection instance with `new T()`,
   which fails to compile (CS7036). When there is no public parameterless ctor, instantiate
   the shadow instance without running the constructor via RuntimeHelpers.GetUninitializedObject
   (mirrors the aggregate no-parameterless-ctor fallback). The shadow instance only invokes
   the projection's stateless Create/Apply event methods.

2. Runtime (#297 multi-identity): when one aggregate is registered against multiple identity
   types (e.g. AggregateStream<CountOfLetters> with both Guid and string ids), the generator
   emits one self-aggregating evolver per TId, all keyed on the aggregate type with a null
   ProjectionType. tryUseAssemblyRegisteredEvolver selected the fallback by aggregate type
   alone and could pick the wrong-TId evolver, whose strongly-typed IGenerated*<TDoc,TId>
   interface checks then all failed, leaving _evolve unwired and tripping the
   'no source-generated dispatcher' backstop. The fallback now only accepts an evolver that
   implements a <TDoc, TId> contract for the current identity type.

Adds a generator regression test; Marten's live_aggregation_with_string_identifiers +
Bug_4185 cover the runtime + generator paths (full EventSourcingTests green). Version → 2.14.1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jeremydmiller
jeremydmiller merged commit ce3ce4c into main Jun 24, 2026
1 check passed
@jeremydmiller
jeremydmiller deleted the fix-evolver-ctor-4185 branch June 24, 2026 01:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant