IonIon
Packages
  • next
  • current
Changelog
GitHub
Packages
  • next
  • current
Changelog
GitHub
  • Version 0.x

    • Release Notes
    • Upgrade Guide
    • Contribution Guide
    • Security Policy
    • Code of Conduct
    • Origin
  • Packages

    • Introduction
    • Container

      • Introduction
      • Prerequisites
      • How to install
      • Container Instance
      • Bindings
      • Dependencies
      • Resolving
      • Contextual Bindings
    • Contracts

      • Introduction
      • How to install
    • Support

      • Introduction
      • How to install
      • Arrays

        • About Arrays
        • Includes All
        • Includes Any
        • Is Array Like
        • Is Concat Spreadable
        • Is Safe Array Like
        • Is Typed Array
        • Merge
      • Concerns

        • About Concerns
        • Prerequisites
        • Concern Class
        • Using Concerns
        • Aliases
        • Conflict Resolution
        • Booting
        • Hooks
        • Edge Cases
        • JSDoc
      • Exceptions

        • About Exceptions
        • Configure Custom Error
        • Configure Stack Trace
        • Get Error Message
        • Custom Errors
      • Facades

        • About Facades
      • Meta

        • About Meta
        • Prerequisites
        • Supported Elements
        • Set & Get
        • Inheritance
        • Outside Changes
        • TC39 Proposal
        • Target Meta
      • Mixins

        • About Mixins
        • New Mixin
        • Apply Mixins
        • Instanceof
        • Inheritance
        • Onward
      • Object

        • About Objects
        • Forget
        • Forget All
        • Get
        • Has
        • Has All
        • Has Any
        • Has Unique ID
        • Is Cloneable
        • Is Populatable
        • Isset
        • Merge
        • Populate
        • Set
        • Unique ID
      • Reflections

        • About reflections
        • Assert Has Prototype Prop.
        • Class Looks Like
        • Class Own Keys
        • Get All Parents Of Class
        • Get Class Prop. Descriptor
        • Get Class Prop. Descriptors
        • Get Constructor Name
        • Get Name Or Desc. Tag
        • Get Parent Of Class
        • Has All Methods
        • Has Method
        • Has Prototype Property
        • Is Callable
        • Is Class Constructor
        • Is Class Method Reference
        • Is Constructor
        • Is Key Safe
        • Is Key Unsafe
        • Is Method
        • Is Subclass
        • Is Subclass Or Looks Like
        • Is WeakKind
      • Misc

        • About Misc.
        • Desc. Tag
        • Empty
        • Is Key
        • Is Primitive
        • Is Property Key
        • Isset
        • Merge Keys
        • To Weak Ref.
      • Callback Wrapper
    • Vuepress Utils

      • Introduction
      • How to install
      • Navigation

        • Archive
      • Plugins

        • Last Updated
      • Components

        • Version Disclaimer
    • XYZ (test package)

Resolving

  • The make() method
    • Dependencies
    • The args Argument
  • The call() method
    • Class Method Reference
    • Callback Wrapper
    • Callback
  • Hooks
    • before()
    • after()

The make() method

To resolve component instances or values from the Service Container, use the make() method. It accepts the following arguments:

  • identifier: Identifier - Target binding identifier.
  • args: any[] = [] - (optional) Eventual arguments to be passed on to class constructor or "factory" callback.
const recorder = container.make('recorder');

When specifying a class constructor as the identifier argument, the make() method will automatically attempt to create a new instance of the given class, even if no binding was registered for it.

class AudioPlayer
{
    // ...not shown...
}

const audio = container.make(AudioPlayer); // new AudioPlayer instance

Dependencies

If the target that must be resolved is a class that has dependencies defined as metadata, then the make() method will automatically resolve them, and inject them into the target class.

import { dependencies } from "@aedart/support/container";

@dependencies('storage')
class TextRecorder
{
    storage = undeinfed;

    constructor(storage) {
        this.storage = storage;
    }
}

// Register binding in the Service Container
container.singleton('storage', () => {
   return new CookieStorage(); 
});


// ...Later in your application
const recorder = container.make(TextRecorder);
console.log(recorder.storage); // CookieStorage

The args Argument

You can also manually specify what arguments a class constructor or "factory" callback should receive, via the args argument.

const recorder = container.make(TextRecorder, [ new CloudStorage() ]);
console.log(recorder.storage); // CloudStorage

warning

When specifying the args argument for make(), any defined dependencies are overwritten by the values in the args array, if a class constructor is requested resolved! In other words, the binding identifiers defined via the dependencies decorator are ignored.

The call() method

The Service Container can also be used to invoke class methods or callbacks. This allows you to resolve a method's dependencies and inject them. The call() method accepts the following arguments:

  • method: Callback | CallbackWrapper | ClassMethodReference - The target callback or class method to invoke.
  • args: any[] = [] - (optional) Eventual arguments to be passed on to class method or callback.
class UsersRepository
{
    @dependencies('users_api_service')
    fetchUser(usersService)
    {
        // ...not shown...
    }
}

// Later in your application
const promise = container.call([UsersRepository, 'fetchUser']);

Class Method Reference

A "class method reference" is an array that holds two values:

  • A class constructor or object instance.
  • The name of the method to be invoked in the target class.
const reference = [AudioPlayer, 'play'];

When given as the method argument, for call(), the target class constructor is automatically resolved (instantiated with eventual dependencies injected). The method is thereafter invoked and output is returned. If the class method has any dependencies defined, then those will be resolved and injected into the method as arguments.

class AudioPlayer
{
    @dependencies('audio_processor', 'my_song')
    play(processor, song) {
        // ...play logic not shown...
        return this;
    }
}

const player = container.call([AudioPlayer, 'play']);

warning

If you specify the args argument for call(), then eventual defined dependencies are overwritten with the values provided in the args array. Thus, the dependencies of the class method are ignored.

const player = container.call(
    [AudioPlayer, 'play'],
    
    // Arguments passed on to "play" method.
    [
        new AudioProcessor(),
        new FavouriteSong()
    ]
);

Callback Wrapper

When specifying a callback wrapper as target for call(), then the callback will be invoked and eventual output is returned. If the wrapper has arguments specified, then they will automatically be applied, the underlying callback is invoked.

warning

Providing the args argument for call() will overwrite eventual arguments set in the callback wrapper!

import { CallbackWrapper } from "@aedart/support";

const wrapped = CallbackWrapper.make((firstname, lastname) => {
    return `Hi ${firstname} ${lastname}`;
}, 'Brian', 'Jackson');

const result = container.call(wrapped, [ 'James', 'Brown' ]);
console.log(result); // Hi James Brown

To define dependencies for a callback wrapper, you must use the wrapper's set() method and specify an array of target binding identifiers for the DEPENDENCIES symbol as key.

import { DEPENDENCIES } from "@aedart/contracts/container";

const wrapped = CallbackWrapper.make((apiClient) => {
    // ...fetch user logic not shown...
    
    return promise;
}).set(DEPENDENCIES, [ 'api_client' ]);

const promise = container.call(wrapped); // Api Client injected into callback...

Callback

The call() can also be used for invoking a regular callback. Any args argument given to call() are passed on to the callback, and eventual output value is returned.

const result = container.call((x) => {
    return x * 2;
}, 4);

console.log(result); // 8

Limitation

At the moment, it is not possible to associate dependencies with a native callback directly. Please use a callback wrapper instead, if you need to inject dependencies into a callback.

Hooks

If you need to react to components or values that are being resolved from the Service Container, then you can use the before() and after() hook methods.

before()

The before() method registers a callback to be invoked before a binding is resolved.

container.before('user', (identifier, args, container) => {
    // ...not shown...
});

after()

The after() method registers a callback to be invoked after a binding has been resolved

container.after('user', (identifier, resolved, container) => {
    // ...not shown...
});
Edit page
Last Updated:
Contributors: alin
Prev
Dependencies
Next
Contextual Bindings