Generator: Create Bridge Pattern
Summary
Add a source generator that produces boilerplate-free, GoF-consistent Bridge pattern scaffolding, separating an abstraction from its implementation with explicit contracts and generated forwarding.
The generator lives in PatternKit.Generators and emits self-contained C# with no runtime PatternKit dependency.
Primary goals:
- Generate the “abstraction” and “implementor” wiring consistently.
- Avoid hand-written forwarding drift.
- Support interface- or abstract-class based implementors.
- Support sync + async members (preserve signatures).
Motivation / Problem
Bridge implementations often repeat:
- Abstraction storing implementor reference
- Forwarding members
- Optional refined abstractions
- Naming collisions and inconsistent wiring
Generator can emit the canonical scaffolding once, consistently.
Supported Targets (must-have)
Bridge generation must support:
- implementor contract:
interface or abstract class
- abstraction host:
partial class / partial record class (struct support optional; v1 can support struct if desired)
V1 scope can focus on:
- generating an abstraction base type that forwards to implementor
- optional generation of a default abstraction implementation
Proposed User Experience
A) Annotate implementor contract, generate abstraction base
[BridgeImplementor]
public partial interface IRenderer
{
void DrawLine(int x1, int y1, int x2, int y2);
ValueTask FlushAsync(CancellationToken ct = default);
}
[BridgeAbstraction(typeof(IRenderer))]
public partial class Shape
{
// user adds domain methods and calls into generated forwarding
}
Generated (representative shape):
public abstract partial class Shape
{
protected Shape(IRenderer implementor);
protected IRenderer Implementor { get; }
protected void DrawLine(int x1, int y1, int x2, int y2)
=> Implementor.DrawLine(x1, y1, x2, y2);
protected ValueTask FlushAsync(CancellationToken ct = default)
=> Implementor.FlushAsync(ct);
}
B) Generate a default refined abstraction (optional)
[BridgeAbstraction(typeof(IRenderer), GenerateDefault = true, DefaultTypeName = "DefaultShape")]
public partial class Shape { }
Generated:
DefaultShape : Shape with minimal constructor.
Attributes / Surface Area
Namespace: PatternKit.Generators.Bridge
Core
Optional:
[BridgeIgnore] for implementor members to exclude from generated forwarding.
Semantics (must-have)
Forwarding
- Generated protected forwarding methods for each implementor member.
- Preserve signatures (no rewriting).
- For interface implementors, forward all members.
- For abstract class implementors, forward only virtual/abstract members (v1).
Construction
- Abstraction must store implementor reference.
- Generated constructor should be
protected.
- Null checking: throw
ArgumentNullException.
Async
- Preserve implementor async signatures.
- Do not rewrite Task/ValueTask; just forward.
Diagnostics (must-have)
PKBRG001 Type marked [BridgeAbstraction] must be partial.
PKBRG002 Implementor type must be interface or abstract class.
PKBRG003 Implementor member unsupported for forwarding (events v1).
PKBRG004 Name conflicts for generated default type.
PKBRG005 Inaccessible implementor members for forwarding.
Generated Code Layout
AbstractionName.Bridge.g.cs
AbstractionName.Bridge.Default.g.cs (optional)
Determinism:
- stable ordering by member name.
Testing Expectations
- Implementor calls are forwarded correctly.
- Null implementor throws.
- Diagnostics: invalid implementor type, name conflicts.
- Async forwarding works.
Acceptance Criteria
Generator: Create Bridge Pattern
Summary
Add a source generator that produces boilerplate-free, GoF-consistent Bridge pattern scaffolding, separating an abstraction from its implementation with explicit contracts and generated forwarding.
The generator lives in
PatternKit.Generatorsand emits self-contained C# with no runtime PatternKit dependency.Primary goals:
Motivation / Problem
Bridge implementations often repeat:
Generator can emit the canonical scaffolding once, consistently.
Supported Targets (must-have)
Bridge generation must support:
interfaceorabstract classpartial class/partial record class(struct support optional; v1 can support struct if desired)V1 scope can focus on:
Proposed User Experience
A) Annotate implementor contract, generate abstraction base
Generated (representative shape):
B) Generate a default refined abstraction (optional)
Generated:
DefaultShape : Shapewith minimal constructor.Attributes / Surface Area
Namespace:
PatternKit.Generators.BridgeCore
[BridgeImplementor]on implementor contractstring? ImplementorTypeName(optional; mostly marker)[BridgeAbstraction(Type implementorType)]on abstraction hoststring ImplementorPropertyName = "Implementor"bool GenerateDefault(default: false)string? DefaultTypeName(default:<AbstractionName>Default)Optional:
[BridgeIgnore]for implementor members to exclude from generated forwarding.Semantics (must-have)
Forwarding
Construction
protected.ArgumentNullException.Async
Diagnostics (must-have)
PKBRG001Type marked[BridgeAbstraction]must bepartial.PKBRG002Implementor type must be interface or abstract class.PKBRG003Implementor member unsupported for forwarding (events v1).PKBRG004Name conflicts for generated default type.PKBRG005Inaccessible implementor members for forwarding.Generated Code Layout
AbstractionName.Bridge.g.csAbstractionName.Bridge.Default.g.cs(optional)Determinism:
Testing Expectations
Acceptance Criteria