library.inversion.factories.md 4.9 KB

Factory Classes

Overview

Factories create component instances in Inversion. The Factory interface defines the contract, with DelegateFactory and InstanceFactory as built-in implementations. Custom factories can implement complex instantiation logic.

Namespace

Inversion

Factory Interface

Declaration

public interface Factory : Object

Method

create(Scope scope) throws Error → Object

Creates a new instance of the component. The scope parameter enables dependency resolution during creation.

public interface Factory : Object {
    public abstract Object create(Scope scope) throws Error;
}

DelegateFactory Class

Overview

DelegateFactory wraps a FactoryDelegate function for instance creation. This is the most commonly used factory, created automatically by container registration methods.

Declaration

public class DelegateFactory : Object, Factory

Constructor

public DelegateFactory(owned FactoryDelegate delegate)

Usage

// Container methods create DelegateFactory internally
container.register_singleton<MyService>((scope) => new MyService());

// Equivalent manual creation
var factory = new DelegateFactory((scope) => new MyService());
container.register_factory<MyService>(factory, Lifecycle.SINGLETON);

With Dependencies

container.register_scoped<OrderService>((scope) => {
    var repo = scope.resolve<IOrderRepository>();
    var logger = scope.resolve<ILogger>();
    return new OrderService(repo, logger);
});

InstanceFactory Class

Overview

InstanceFactory always returns a pre-existing instance. Used for scope-local instance caching and registering already-created objects.

Declaration

public class InstanceFactory : Object, Factory

Properties

Property Type Description
registration Registration Associated registration

Constructor

public InstanceFactory(Registration registration, Object instance)

Usage

// Register an existing instance
var existing_service = new MyConfiguredService();
var registration = new Registration(typeof(MyConfiguredService), 
    new InstanceFactory(reg, existing_service), 
    Lifecycle.SINGLETON);

FactoryDelegate

Declaration

public delegate Object FactoryDelegate(Scope scope) throws Error;

The delegate signature used by DelegateFactory. Receives the current scope for resolving dependencies.

Parameters

  • scope: The active scope for dependency resolution

Returns

  • A new instance of the component

Example

FactoryDelegate factory = (scope) => {
    var dependency = scope.resolve<IDependency>();
    return new MyService(dependency);
};

Custom Factory Implementation

When to Implement

  • Complex object construction
  • Integration with external frameworks
  • Conditional instance creation
  • Pool-based instance management

Example: Pool Factory

public class PoolFactory : Object, Factory {
    private Type element_type;
    private Queue<Object> pool = new Queue<Object>();
    
    public PoolFactory(Type element_type) {
        this.element_type = element_type;
    }
    
    public Object create(Scope scope) throws Error {
        Object? pooled = pool.try_pop();
        if (pooled != null) {
            return pooled;
        }
        return Object.new(element_type);
    }
    
    public void return_to_pool(Object instance) {
        pool.push(instance);
    }
}

// Usage
var pool_factory = new PoolFactory(typeof(PooledObject));
container.register_factory_type(typeof(PooledObject), pool_factory, Lifecycle.TRANSIENT);

Example: Lazy Factory

public class LazyFactory : Object, Factory {
    private Factory inner_factory;
    private Object? cached_instance;
    private Mutex mutex = Mutex();
    
    public LazyFactory(Factory inner) {
        this.inner_factory = inner;
    }
    
    public Object create(Scope scope) throws Error {
        mutex.lock();
        if (cached_instance == null) {
            cached_instance = inner_factory.create(scope);
        }
        mutex.unlock();
        return cached_instance;
    }
}

Factory Selection by Lifecycle

Lifecycle Factory Usage
TRANSIENT Factory called on every resolve
SCOPED Factory called once per scope, then cached
SINGLETON Factory called once per container, then cached

Integration with Registration

Factories are associated with registrations:

// DelegateFactory created internally
var reg = container.register_transient<MyService>((s) => new MyService());

// Access factory if needed
var factory = reg.factory;

Inversion provides Factory interface with DelegateFactory for delegate-based creation and InstanceFactory for existing instances, supporting custom implementations for complex instantiation scenarios.