library.inversion.scope.md 5.4 KB

Scope Class

Overview

Scope manages the lifecycle of scoped components. Created from a Container, each scope maintains its own cache of scoped instances and can have local registrations not visible to other scopes. Useful for per-request lifecycles in web applications.

Namespace

Inversion

Class Declaration

public class Scope : Object

Properties

Property Type Description
container Container The container this scope belongs to
scope_lifecycle Lifecycle Lifecycle mode for this scope

Creation

Scopes are created from a container:

var container = new Container();
var scope = container.create_scope();       // Scoped lifecycle
var transient_scope = container.create_transient_scope();  // Transient lifecycle

Resolution Methods

resolve<T>() throws Error → T

Resolves a single instance of type T.

try {
    var logger = scope.resolve<ILogger>();
    var service = scope.resolve<UserService>();
} catch (Error e) {
    stderr.printf("Resolution failed: %s\n", e.message);
}

resolve_type(Type type) throws Error → Object

Non-generic resolution by Type.

var instance = scope.resolve_type(typeof(ILogger));

resolve_all<T>() throws Error → Enumerable<Object>

Resolves all registered implementations of type T.

var all_handlers = scope.resolve_all<IHandler>();
all_handlers.iterate((h) => {
    ((IHandler)h).handle(request);
});

resolve_all_type(Type type) throws Error → Enumerable<Object>

Non-generic version for all implementations.

var all_loggers = scope.resolve_all_type(typeof(ILogger));

Query Methods

is_registered(Type type) → bool

Checks if type has any registration (local or from container).

if (scope.is_registered(typeof(ILogger))) {
    var logger = scope.resolve<ILogger>();
}

is_locally_registered(Type type) → bool

Checks if type has a scope-local registration only.

if (!scope.is_locally_registered(typeof(RequestContext))) {
    scope.register_local_scoped<RequestContext>((s) => new RequestContext());
}

get_local_registrations(Type service_type) → Enumerable<Registration>

Gets all local registrations for a type.

var local_regs = scope.get_local_registrations(typeof(IPlugin));

Local Registration Methods

Local registrations exist only within the scope. Singletons are not allowed in local registrations.

register_local<T>(owned FactoryDelegate factory_func, Lifecycle lifecycle) → Registration

Registers with specified lifecycle. Precondition: lifecycle != SINGLETON.

scope.register_local<RequestContext>((s) => new RequestContext(), Lifecycle.SCOPED);

register_local_transient<T>(owned FactoryDelegate factory_func) → Registration

Registers as transient (new instance per resolve).

scope.register_local_transient<RequestData>((s) => new RequestData());

register_local_scoped<T>(owned FactoryDelegate factory_func) → Registration

Registers as scoped (one instance within this scope).

scope.register_local_scoped<Session>((s) => new Session());

register_local_type(Type implementation_type, owned FactoryDelegate factory_func, Lifecycle lifecycle) → Registration

Non-generic local registration.

register_local_factory<T>(Factory factory, Lifecycle lifecycle) → Registration

Local registration with custom factory.

register_local_factory_type(Type implementation_type, Factory factory, Lifecycle lifecycle) → Registration

Non-generic factory registration.

Resolution Behavior

Lifecycle Handling

Registration Lifecycle Behavior
SINGLETON Returns container-wide singleton
SCOPED Returns cached instance for this scope
TRANSIENT Creates new instance each time

Resolution Order

  1. Check local registrations first
  2. Fall back to container registrations
  3. Apply lifecycle rules

Lifecycle Constraints

  • Singleton scope cannot resolve scoped registrations (throws ILLEGAL_LIFECYCLE_COMBINATION)

    // This throws ILLEGAL_LIFECYCLE_COMBINATION
    var singleton_scope = new Scope(container, Lifecycle.SINGLETON);
    var scoped_instance = singleton_scope.resolve<ScopedService>();  // Error!
    

Usage Patterns

Per-Request Scope (Web Applications)

void handle_request(Request req) {
    var scope = container.create_scope();
    
    // Register request-specific context
    scope.register_local_scoped<RequestContext>((s) => new RequestContext(req));
    
    // Resolve handler - gets same RequestContext within this scope
    var handler = scope.resolve<RequestHandler>();
    handler.process();
}

Nested Dependencies

// All services in same scope share scoped instances
var scope = container.create_scope();
var service_a = scope.resolve<ServiceA>();  // Gets scoped IRepository
var service_b = scope.resolve<ServiceB>();  // Gets SAME IRepository instance

Scope Isolation

var scope1 = container.create_scope();
var scope2 = container.create_scope();

var user1 = scope1.resolve<ScopedUser>();  // Instance A
var user2 = scope2.resolve<ScopedUser>();  // Instance B (different)

The Scope class provides scoped instance management with local registration support, resolution methods for single and multiple implementations, and lifecycle-aware caching for per-request or per-unit-of-work patterns.