-
Notifications
You must be signed in to change notification settings - Fork 34
Autowire
Autowiring allows you to manage services in the container with minimal configuration. It reads the type-hints on your constructor (or other methods) and automatically passes the correct services to each method. Node Dependency Injection's autowiring is designed to be predictable: if it is not absolutely clear which dependency should be passed, you'll see an actionable exception.
Thanks to compiled container, there is no runtime overhead for using autowiring.
Start by creating a Base64 transformer class:
export default class Base64Transformer
{
public transform(value: string): string
{
return new Buffer(value).toString('base64');
}
}
And now a Some client using this transformer:
export default class SomeClient
{
constructor(
private readonly transformer: Base64Transformer,
) {}
async execute(value: string): Promise<void>
{
const transformedString = this.transformer.transform(value)
…
}
}
If you're using the default services.yaml configuration, both classes are automatically registered as services and configured to be autowired. This means you can use them immediately without any configuration.
However, to understand autowiring better, the following examples explicitly configure both services:
# config/services.yaml
services:
_defaults:
autowire: true
rootDir: ../src # that is from the file path
You might also find yourself type-hinting abstractions (e.g. interfaces) instead of concrete classes as it replaces your dependencies with other objects.
To follow this best practice, suppose you decide to create a TransformerInterface:
export default interface Transformer
{
transform(value: string): string;
}
Then, you update Base64Transformer to implement it:
export default class Base64Transformer implements Transformer
{
transform(value: string): string
{
return new Buffer(value).toString('base64');
}
}
Now that you have an interface, you should use this as your type-hint:
export default class SomeClient
{
constructor(
private readonly transformer: Transformer,
) {}
async execute(value: string): Promise<void>
{
const transformedString = this.transformer.transform(value)
…
}
}
If you are transpiling your Typescript may you need to dump the some kind of service configuration file.
import {ContainerBuilder, Autowire, ServiceFile} from 'node-dependency-injection'
const container = new ContainerBuilder(
false,
'/path/to/src'
)
const autowire = new Autowire(container)
autowire.serviceFile = new ServiceFile('/some/path/to/dist/services.yaml')
await autowire.process()
My proposal for load configuration file in a production environment with transpiling/babel compilation:
if (process.env.NODE_ENV === 'dev') {
this._container = new ContainerBuilder(false, '/src');
this._autowire = new Autowire(this._container);
this._autowire.serviceFile = new ServiceFile('/some/path/to/dist/services.yaml');
await this._autowire.process();
} else {
this._container = new ContainerBuilder(false, '/dist');
this._loader = new YamlFileLoader(this._container);
await this._loader.load('/some/path/to/dist/services.yaml');
}
await this._container.compile();
You can also exclude some specific folder from your root directory
# /path/to/services.yml
services:
_defaults:
autowire: true
rootDir: "../path/to/src"
exclude: ["ToExclude"]
So, in that case, ../path/to/src/ToExclude
will be automatically excluded from container.
Copyright © 2023-2024 Mauro Gadaleta