Skip to content

Conversation

@kgrigorev
Copy link
Contributor

No description provided.

@kgrigorev kgrigorev self-assigned this Nov 20, 2025
Introduce a new comprehensive generic binding API that provides type safety,
ergonomic usage, and fail-fast validation while maintaining full compatibility
with the existing reflection-based API.

Key Features:
- Type-safe bindings using Go generics (type parameters)
- Fail-fast validation at binding time (not resolution time)
- Clean, idiomatic Go API design
- Returns *Binding for compatibility and method chaining
- Full feature parity with existing API

New Files:
- binding_generic.go: Core generic binding functions
  * Bind[T]() - Type-safe binding creation
  * BindTo[F, T]() - Explicit type relationship with validation
  * BindInstance[T]() - Instance binding with type safety
  * BindProvider[T]() - Provider binding with type safety
  * BindProviderFunc[T]() - Provider with dependency injection

- multi_binding_generic.go: Generic multi-binding functions
  * BindMulti[T]() - Type-safe multi-binding
  * BindMultiTo[F, T]() - Explicit multi-binding type relationship
  * BindMultiInstance[T]() - Multi-binding instance
  * BindMultiProvider[T]() - Multi-binding provider

- map_binding_generic.go: Generic map-binding functions
  * BindMap[T]() - Type-safe map-binding
  * BindMapTo[F, T]() - Explicit map-binding type relationship
  * BindMapInstance[T]() - Map-binding instance
  * BindMapProvider[T]() - Map-binding provider

- injector_generic.go: Generic injector helper functions
  * GetInstance[T]() - Type-safe instance retrieval
  * GetAnnotatedInstance[T]() - Type-safe annotated instance retrieval
  * RequestInjection[T]() - Type-safe injection request
  * Override[T]() - Type-safe override
  * BindInterceptor[T]() - Type-safe interceptor binding
  * GetMultiInstance[T]() - Convenience for multi-bindings
  * GetMapInstance[T]() - Convenience for map-bindings

- example_generic_api.go: Comprehensive examples and API comparison

Benefits:
- Compile-time type checking where possible
- No type assertions needed when retrieving instances
- All validation happens at binding time (fail-fast)
- Clean and intuitive API surface
- Fully compatible with existing code
- Can mix old and new API freely

Migration Path:
The new API is fully interchangeable with the existing API:
- Old: injector.Bind((*Logger)(nil)).To(ConsoleLogger{})
- New: Bind[Logger](injector).To(&ConsoleLogger{})

Both APIs work with the same underlying *Binding type and *Injector.
Refactor the generic binding API to eliminate chaining and use the idiomatic
Go functional options pattern. This makes the API cleaner, more concise, and
easier to use.

Major Changes:

1. **Functional Options Pattern**
   - Introduce BindingOption type and option functions
   - WithAnnotation(string) - set annotation
   - WithScope(Scope) - set custom scope
   - AsSingleton() - convenience for singleton scope
   - AsChildSingleton() - convenience for child singleton scope
   - AsEagerSingleton() - mark as eager singleton
   - Options are composable and extensible

2. **Combined Bind+To in Single Function**
   - Old: Bind[Logger](injector).To(&ConsoleLogger{})
   - New: Bind[Logger, *ConsoleLogger](injector)
   - Both "from" and "to" types specified in type parameters
   - No more chaining needed for basic bindings
   - Type validation happens at binding time (fail-fast)

3. **Simplified Function Signatures**
   All binding functions now follow this pattern:
   - Bind[F, T](injector, ...BindingOption) *Binding
   - BindMulti[F, T](injector, ...BindingOption) *Binding
   - BindMap[F, T](injector, key, ...BindingOption) *Binding
   - BindInstance[T](injector, instance, ...BindingOption) *Binding
   - BindProvider[T](injector, provider, ...BindingOption) *Binding

4. **Updated Override Functions**
   - Override[F, T](injector, annotation, ...BindingOption) *Binding
   - OverrideInstance[T](injector, annotation, instance, ...BindingOption) *Binding
   - Follows same pattern as main binding functions

Benefits:
- More concise: Bind[Logger, *ConsoleLogger](injector, AsSingleton())
- No chaining: All configuration in single function call
- Idiomatic Go: Follows established functional options pattern
- Extensible: Easy to add new options without breaking API
- Clean: Clear separation between required and optional parameters
- Type-safe: Full compile-time type checking where possible

Example Comparisons:

// Before:
Bind[Logger](injector).To(&ConsoleLogger{}).AnnotatedWith("console").In(Singleton)

// After:
Bind[Logger, *ConsoleLogger](injector, WithAnnotation("console"), AsSingleton())

// Before:
BindMulti[Plugin](injector).To(&PluginA{}).AnnotatedWith("prod").In(Singleton)

// After:
BindMulti[Plugin, *PluginA](injector, WithAnnotation("prod"), AsSingleton())

The new API is cleaner, more Go-idiomatic, and easier to read and maintain.
Consolidate all generic binding API implementation into a single well-organized
file for better maintainability and discoverability.

Changes:
- Merge binding_generic.go, multi_binding_generic.go, map_binding_generic.go,
  and injector_generic.go into generics.go
- Rename example_generic_api.go to generics_example.go for consistency
- Organize generics.go with clear section comments:
  * Functional Options
  * Core Binding Functions
  * Multi-Binding Functions
  * Map-Binding Functions
  * Injector Helper Functions

Benefits:
- Single source of truth for generic API
- Easier to navigate and maintain
- Clear file naming convention (generics.go, generics_example.go)
- Better organization with section markers
- Reduced file clutter

File structure:
- generics.go (~1340 lines) - Complete generic API implementation
- generics_example.go (~470 lines) - 15 comprehensive examples
Added comprehensive type safety enhancements to the generic binding API:

Type-Safe Provider Functions:
- Added Provider0-5 and ProviderWithError0-5 type aliases
- Added BindProvider1-5 and BindProviderWithError1-5 functions
- These provide compile-time type safety for provider dependencies
- Eliminates need for interface{} in provider function signatures

Interface Verification:
- Added Implements[I, T]() for runtime interface verification
- Added MustImplement[I, T]() for defensive programming patterns
- Both provide clear panic messages on type mismatches

Comprehensive Examples:
- Added 6 new examples (16-21) demonstrating type safety features
- Examples show compile-time vs runtime verification
- Demonstrate type-safe providers with 1-5 dependencies
- Include comparison showing benefits over BindProviderFunc
- Show advanced patterns with complex dependency graphs

All code compiles and maintains full backward compatibility.
@kgrigorev kgrigorev force-pushed the claude/redesign-binding-api-generics-017S6YMM1v9BDn7Efs4zqhmq branch from 19b8cde to f70f181 Compare November 20, 2025 22:37
@kgrigorev kgrigorev closed this Nov 20, 2025
@kgrigorev kgrigorev changed the title Claude/redesign binding api generics 017 s6 ymm1v9 b dn7 efs4zqhmq redesign binding api with generics Nov 20, 2025
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.

2 participants