Context-Aware Factory Functions
Parsley provides a specialized way to handle on-demand service resolution through context-aware factory functions. By using the RegisterFactory[T] function from the pkg/features package, you can register a factory that returns a function capable of resolving a service of type T whenever it is called.
The FactoryFunc Type
A context-aware factory function is represented by the FactoryFunc[T] type:
type FactoryFunc[T any] func(ctx context.Context) (T, error)
This function takes a context.Context and returns an instance of type T (or an error). When invoked, it uses the underlying Parsley resolver to find and return the requested service.
Registering a Factory
To register a context-aware factory, use the features.RegisterFactory[T] function. This function registers the FactoryFunc[T] type in the provided service registry.
func RegisterFactory[T any](registry types.ServiceRegistry, scope types.LifetimeScope) error
Example
The following example demonstrates how to register and use a context-aware factory for a Greeter service.
package main
import (
"context"
"fmt"
"github.com/matzefriedrich/parsley/pkg/features"
"github.com/matzefriedrich/parsley/pkg/registration"
"github.com/matzefriedrich/parsley/pkg/resolving"
"github.com/matzefriedrich/parsley/pkg/types"
)
type Greeter interface {
Greet() string
}
type greeter struct{}
func (g *greeter) Greet() string {
return "Hello, Parsley!"
}
func NewGreeter() Greeter {
return &greeter{}
}
func main() {
registry := registration.NewServiceRegistry()
// Register the actual service
_ = registration.RegisterSingleton(registry, NewGreeter)
// Register a FactoryFunc for the Greeter service
_ = features.RegisterFactory[Greeter](registry, types.LifetimeSingleton)
resolver := resolving.NewResolver(registry)
ctx := context.Background()
// Resolve the factory function
factory, _ := resolving.ResolveRequiredService[features.FactoryFunc[Greeter]](ctx, resolver)
// Use the factory to resolve the service on demand
svc, _ := factory(ctx)
fmt.Println(svc.Greet())
}
Use Cases
Context-aware factory functions are particularly useful when you need to:
- Deferred Resolution: Resolve a service only when a specific condition is met at runtime.
- Contextual Resolution: Pass a specific context to the resolution process, which is useful for tracing, logging, or accessing request-scoped values.
- Circular Dependencies: Break circular dependencies by resolving one of the services on demand rather than at construction time.